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 librararies 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 *************************************<+>*************************************/
61 #ifdef _SUN_OS /* to get the define for NOFILE */
62 #include <sys/param.h>
64 #include <sys/types.h>
67 #include <X11/apollosys.h> /* for pid_t struct in hp-ux sys/types.h */
69 #include <sys/socket.h>
71 #include <netinet/in.h>
76 #include <X11/Intrinsic.h>
77 #include <X11/Xutil.h>
78 #include <X11/Xatom.h>
79 #include <X11/StringDefs.h>
80 #include <X11/keysymdef.h>
81 #include <X11/SM/SMlib.h>
85 # define Va_start(a,b) va_start(a,b)
88 #include <Dt/Message.h>
89 #include <Dt/CommandM.h>
90 #include <Dt/Connect.h>
93 #include <Dt/UserMsg.h>
94 #include <Dt/SessionM.h>
95 #include <Dt/EnvControlP.h>
96 #include <Dt/Utility.h>
97 #include <Dt/MsgLog.h>
99 #include <Dt/CmdInv.h>
100 #include <Dt/ActionUtilP.h>
103 #include "SmResource.h"
105 #include "SmCommun.h"
106 #include "SmRestore.h"
107 #include "SmProtocol.h"
108 #include "SmConMgmt.h"
111 #include "SmGlobals.h"
117 #include <X11/Xlibint.h>
123 static const char * DISPLAY_NAME_EQUAL = "DISPLAY=";
124 static const char * DISPLAY_NAME = "DISPLAY";
125 static char * savedDisplay = NULL;
131 #define MAXPATHSM 1023
132 #define MAX_QUOTE_DEPTH 10
134 #define SM_MAX_ARGS MAXLINE
136 #if defined (SVR4) || defined (__osf__)
137 #define REMOTE_CMD_STRING "rsh %s -n %s &"
139 #define REMOTE_CMD_STRING "remsh %s -n %s &"
148 unsigned char *hostPtr;
149 unsigned char *cmdPtr;
153 * Variables global to this module only
155 static XtResource settingsResources[] =
157 {SmNaccelNum, SmCaccelNum, XtRInt, sizeof(int),
158 XtOffset(SessionSettingsPtr, accelNum),
159 XtRImmediate, (XtPointer) -1},
160 {SmNaccelDenom, SmCaccelDenom, XtRInt, sizeof(int),
161 XtOffset(SessionSettingsPtr, accelDenom),
162 XtRImmediate, (XtPointer) -1},
163 {SmNthreshold, SmCthreshold, XtRInt, sizeof(int),
164 XtOffset(SessionSettingsPtr, threshold),
165 XtRImmediate, (XtPointer) -1},
167 {SmNtimeout, SmCtimeout, XtRInt, sizeof(int),
168 XtOffset(SessionSettingsPtr, timeout),
169 XtRImmediate, (XtPointer) -1},
170 {SmNinterval, SmCinterval, XtRInt, sizeof(int),
171 XtOffset(SessionSettingsPtr, interval),
172 XtRImmediate, (XtPointer) -1},
173 {SmNpreferBlank, SmCpreferBlank, XtRInt, sizeof(int),
174 XtOffset(SessionSettingsPtr, preferBlank),
175 XtRImmediate, (XtPointer) 0},
176 {SmNallowExp, SmCallowExp, XtRInt, sizeof(int),
177 XtOffset(SessionSettingsPtr, allowExp),
178 XtRImmediate, (XtPointer) 0},
180 {SmNfontPath, SmCfontPath, XtRString, sizeof(String),
181 XtOffset(SessionSettingsPtr, fontDirs), XtRString, (XtPointer) ""},
183 {SmNkeyClick, SmCkeyClick, XtRInt, sizeof(int),
184 XtOffset(SessionSettingsPtr, kbdState.key_click_percent),
185 XtRImmediate, (XtPointer) -1},
186 {SmNbellPercent, SmCbellPercent, XtRInt, sizeof(int),
187 XtOffset(SessionSettingsPtr, kbdState.bell_percent),
188 XtRImmediate, (XtPointer) -1},
189 {SmNbellPitch, SmCbellPitch, XtRInt, sizeof(int),
190 XtOffset(SessionSettingsPtr, kbdState.bell_pitch),
191 XtRImmediate, (XtPointer) -1},
192 {SmNbellDuration, SmCbellDuration, XtRInt, sizeof(int),
193 XtOffset(SessionSettingsPtr, kbdState.bell_duration),
194 XtRImmediate, (XtPointer) -1},
195 {SmNledMask, SmCledMask, XtRInt, sizeof(int),
196 XtOffset(SessionSettingsPtr, kbdState.led_mask),
197 XtRImmediate, (XtPointer) 0},
198 {SmNglobalRepeats, SmCglobalRepeats, XtRInt, sizeof(int),
199 XtOffset(SessionSettingsPtr, kbdState.global_auto_repeat),
200 XtRImmediate, (XtPointer) 2},
201 {SmNautoRepeats, SmCautoRepeats, XtRString, sizeof(String),
202 XtOffset(SessionSettingsPtr, autoRepeats), XtRString, (XtPointer) ""},
204 {SmNbuttonMap, SmCbuttonMap, XtRString, sizeof(String),
205 XtOffset(SessionSettingsPtr, buttonMap), XtRString, (XtPointer) ""},
207 {SmNnumKeyCode, SmCnumKeyCode, XtRInt, sizeof(int),
208 XtOffset(SessionSettingsPtr, numKeyCode), XtRImmediate, (XtPointer) 0},
209 {SmNkeySymsPerKey, SmCkeySymsPerKey, XtRInt, sizeof(int),
210 XtOffset(SessionSettingsPtr, keySymPerCode),
211 XtRImmediate, (XtPointer) 0},
212 {SmNkeySyms, SmCkeySyms, XtRString, sizeof(String),
213 XtOffset(SessionSettingsPtr, keySyms), XtRString, (XtPointer) ""},
215 {SmNmaxKeyPerMod, SmCmaxKeyPerMod, XtRInt, sizeof(int),
216 XtOffset(SessionSettingsPtr, maxKeyPerMod),
217 XtRImmediate, (XtPointer) 0},
218 {SmNmodMap, SmCmodMap, XtRString, sizeof(String),
219 XtOffset(SessionSettingsPtr, modSyms),
220 XtRString, (XtPointer) ""},
222 {SmNdidQuerySettings, SmCdidQuerySettings, XtRBoolean, sizeof(Boolean),
223 XtOffset(SessionSettingsPtr, didQuery),
224 XtRImmediate, (XtPointer) False},
225 {SmNshutDownState, SmCshutDownState, XtRInt, sizeof(int),
226 XtOffset(SessionSettingsPtr, confirmMode),
227 XtRImmediate, (XtPointer) 1},
228 {SmNshutDownMode, SmCshutDownMode, XtRInt, sizeof(int),
229 XtOffset(SessionSettingsPtr, startState),
230 XtRImmediate, (XtPointer) 4},
234 * Variables used for parsing code
237 static unsigned char fallBackLine[MAXLINE+2]; /* line buffer */
238 static unsigned char *line; /* line buffer */
239 static FILE *cfileP = NULL; /* fopen'ed configuration file or NULL */
240 static int linec = 0; /* line counter for parser */
241 static unsigned char *parseP = NULL; /* pointer to parse string */
242 static int fileSize = 0;
243 char **smExecArray = NULL;
246 * Variables used for remote execution
248 static int numRemoteExecs = 0;
249 unsigned char *remoteBuf[MAX_SCREENS_SAVED];
250 unsigned int actRemoteSize[MAX_SCREENS_SAVED];
251 RemoteReq remoteBufPtr[MAX_REMOTE_CLIENTS];
252 static char localHost[MAXHOSTNAMELEN];
253 static char ** ignoreEnvPtr = NULL;
256 * Timeout for workspace manager handshake
258 static Boolean wmTimeout;
261 * These lines were added to support the builtin
265 char tmpExecWmFile[MAXPATHSM+1];
266 static Boolean localWmLaunched = False;
269 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
270 * End of lines were added to support the builtin
285 "*XmTextField*FontList",
286 "*DtEditor*textFontList",
291 static char *fontclass[] = {
299 "*XmTextField*FontList",
300 "*DtEditor*textFontList",
309 static int RestoreSettings( void ) ;
310 static int RestoreClients( void ) ;
311 static unsigned char * GetNextLine( void ) ;
312 static unsigned int PeekAhead( unsigned char *, unsigned int ) ;
313 static unsigned char * GetSmartString( unsigned char **) ;
314 static void ForkWM( void ) ;
315 static int FillCmdBuf( unsigned char *, unsigned char **,
316 unsigned int *, unsigned int *,
317 unsigned int, unsigned int *) ;
318 static int FillRemoteBuf( unsigned char *, unsigned char *,
319 unsigned char *, unsigned char **,
320 unsigned int *, unsigned int *, unsigned int) ;
321 static int FillHintBuf(unsigned char *, unsigned char **,
322 unsigned int *, unsigned int *,
323 unsigned int, unsigned int *);
324 static void WaitForWM( void ) ;
325 static void HandleWMClientMessage(Widget smWidget, XtPointer dummy,
327 static void WaitWMTimeout( XtPointer , XtIntervalId *) ;
328 static void FixEnvironmentData( void ) ;
329 static void ResetScreenInfo(unsigned char **,
330 int *, unsigned int *,
333 static void RemoteRequestFailed(char *, void *);
334 static void RemoteRequestSucceeded(char *, void *);
336 static void SetTemporaryDisplay (
339 int RestorePreferences(char *filename);
341 static void RestoreDisplay (
344 static Boolean StartLocalClient (
350 Boolean useIgnoreEnvResource);
352 static Boolean StartRemoteClient (
358 Boolean useIgnoreEnvResource);
360 static Boolean CheckRequiredProperties (
361 XSMPClientDBRecPtr pDbRec,
362 char * databaseName);
364 static Boolean CheckRequiredFields (
365 ProxyClientDBRecPtr pDbRec,
369 static void LogXSMPOpenDatabaseFailure (
371 DtMsgLogType msgType,
374 static void LogMissingPropertyMessage (
375 XSMPClientDBRecPtr pDbRec,
378 DtMsgLogType msgType);
380 static void LogCWDMessage (
385 static char ** RemoveEnvironmentVars (
388 static void MarkFileDescriptors (
394 /*************************************<->*************************************
401 * Sets _DT_SM_STATE_INFO for dtstyle indicating compatibility mode
414 * The only thing dtstyle should be looking at is the compatMode
416 *************************************<->***********************************/
418 SetCompatState( void )
423 * BEFORE any clients are started
424 * set a property on the top level window
425 * which lets the style manager know what state the sm is in
427 state.flags = SM_STATE_ALL;
428 state.smStartState = 0;
429 state.smConfirmMode = 0;
430 state.smCompatMode = True;
431 state.smSendSettings = False;
432 state.smCoverScreen = True;
433 state.smLockOnTimeoutStatus = smGD.lockOnTimeoutStatus;
434 state.smCycleTimeout = 0;
435 state.smLockTimeout = 0;
436 state.smSaverTimeout = 0;
438 state.smDisplaySpecific = smGD.displaySpecific;
440 _DtSetSmState(smGD.display, smGD.topLevelWindow, &state);
442 XFlush(smGD.display);
446 } /* END OF FUNCTION SetCompatState */
449 /*************************************<->*************************************
456 * This function fiddles with our signal handling and calls the
457 * system() function to invoke a unix command.
462 * pchCmd = string with the command we want to exec.
470 * The system() command is touchy about the SIGCLD behavior. Restore
471 * the default SIGCLD handler during the time we run system().
473 *************************************<->***********************************/
476 SystemCmd (char *pchCmd)
478 void (*signalHandler) ();
480 signalHandler = (void (*)())signal (SIGCHLD, SIG_DFL);
484 signal (SIGCHLD, signalHandler);
485 } /* END OF FUNTION SystemCmd */
489 /*************************************<->*************************************
505 * When this routine is finished, all settings and resources will be restored.
506 * Clients may not be, as they are actually restored by different processes.
508 *************************************<->***********************************/
514 char convertCommand[MAXPATHSM+1];
516 Boolean fixedBuffer = False;
519 Boolean useXrmDB = False;
522 * Restore all the X settings which were active at the time of shutdown
526 if (smGD.sessionType == HOME_SESSION)
527 smSettings.startState = DtSM_HOME_STATE;
529 smSettings.startState = DtSM_CURRENT_STATE;
532 * BEFORE any clients are started
533 * set a property on the top level window
534 * which lets the style manager know what state the sm is in
536 state.flags = SM_STATE_ALL;
537 state.smStartState = smSettings.startState;
538 state.smConfirmMode = smSettings.confirmMode;
539 state.smCompatMode = smGD.compatMode;
540 state.smSendSettings = !smRes.querySettings;
541 state.smLockOnTimeoutStatus = smGD.lockOnTimeoutStatus;
542 state.smCycleTimeout = smSaverRes.cycleTimeout;
543 state.smLockTimeout = smSaverRes.lockTimeout;
544 state.smSaverTimeout = smSaverRes.saverTimeout;
545 state.smRandom = smSaverRes.random;
546 state.smDisplaySpecific = smGD.displaySpecific;
548 _DtSetSmState(smGD.display, smGD.topLevelWindow, &state);
550 saver.saverList = smGD.saverList;
551 _DtSetSmSaver(smGD.display, smGD.topLevelWindow, &saver);
554 * Set up the Property telling all applications what session is being
557 XaSmRestoreMode = XInternAtom(smGD.display, _XA_DT_RESTORE_MODE, False);
558 XChangeProperty(smGD.display, RootWindow(smGD.display, 0),
559 XaSmRestoreMode, XA_STRING, 8, PropModeReplace,
560 (unsigned char *)smGD.restoreSession, strlen(smGD.restoreSession));
561 XFlush(smGD.display);
564 * Check the session database and either parse it as an
565 * Xrm-database or the CDE1.0 format
567 if ((pchar = strrchr (smGD.clientPath, '/')) != NULL)
570 if ((*pchar != '\0') && (!strcmp (pchar, SM_CLIENT_FILE2)))
576 return (StartXSMPSession (smGD.clientPath));
580 * Malloc line for parsing.
582 status = stat(smGD.clientPath, &buf);
585 fileSize = buf.st_size;
588 if (fileSize < MAXLINE + 1)
590 fileSize = MAXLINE + 1;
593 line = (unsigned char *) malloc ((fileSize + 1) * sizeof(char *));
597 fileSize = MAXLINE + 1;
600 cfileP = fopen(smGD.clientPath, "r");
603 PrintErrnoError(DtError, smNLS.cantOpenFileString);
604 if (!fixedBuffer && line)
606 SM_FREE((char *)line);
613 if (!fixedBuffer && line)
615 SM_FREE((char *)line);
624 /*************************************<->*************************************
631 * Start up the window manager. The default is to start dtmwm unless
632 * another one is specified in a resource.
645 * When this routine is finished, all settings and resources will be restored.
646 * Clients may not be, as they are actually restored by different processes.
648 *************************************<->***********************************/
652 char wmStartupErrorString[(2 * MAXPATHSM) + 1];
653 char localWmErrorString[(2 * MAXPATHSM) + 1];
654 Boolean goodWmStartup = True;
657 if((smGD.wmStartup == NULL) || (*smGD.wmStartup == 0))
663 CreateExecString(smGD.wmStartup);
666 * check to see if the wmStartup string exists and is
669 status = access(smExecArray[0], F_OK | X_OK);
672 goodWmStartup = False;
673 CreateExecString(CDE_INSTALLATION_TOP "/bin/dtwm");
676 if(smExecArray[0] != NULL)
678 (void) StartClient(smExecArray[0], smExecArray, NULL, NULL,
679 NULL, False, False, -1);
684 * We used to start the message server before the window
685 * manager and then if the message server did not start
686 * we would exit. Now we start the window manager, then
687 * start the message server and then wait for the window
688 * manager. This seems to improve performance.
693 if (goodWmStartup == False)
695 sprintf(wmStartupErrorString, GETMESSAGE(16, 7,
696 "The wmStartupCommand resource is set to:\n\n"
698 "This file does not exist or is not executable.\n"
699 CDE_INSTALLATION_TOP "/bin/dtwm will be started "
702 PrintError(DtError, wmStartupErrorString);
708 * These lines were added to support the builtin
712 if (localWmLaunched && wmTimeout)
714 if (!smGD.userSetWaitWmTimeout)
716 smRes.waitWmTimeout = smGD.savedWaitWmTimeout;
719 localWmLaunched = False;
721 * A special version of a built-in Xterminal dtwm
722 * was attempted and failed.
723 * Try to launch .../dt/bin/dtwm instead
726 CreateExecString(CDE_INSTALLATION_TOP "/bin/dtwm");
727 if(smExecArray[0] != NULL)
729 (void) StartClient(smExecArray[0], smExecArray, NULL,
730 NULL, NULL, False, False, -1);
733 sprintf(localWmErrorString, GETMESSAGE(16, 9,
734 "The following window manager did not start:\n\n"
736 "This message indicates you tried to start a\n"
737 "window manager that is built into an X terminal.\n"
738 "This will only work with X terminals that support this protocol.\n"
739 CDE_INSTALLATION_TOP "/bin/dtwm will be started instead.\n"),
741 PrintError(DtError, localWmErrorString);
744 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
745 * End of lines were added to support the builtin
754 /*************************************<->*************************************
761 * Reloads RESOURCE_MANAGER during running session
773 *************************************<->***********************************/
776 ReloadResources(void)
779 * Load sys.resources and .Xdefaults
781 RestoreResources(True,
788 * Merge _DT_SM_PREFERENCES
790 RestorePreferences(NULL);
796 /*************************************<->*************************************
798 * RestoreResources (errorHandlerInstalled, options ... )
803 * Calls routines responsible for restoring resources.
804 * Resources are restored by a fork and exec of dtsession_res.
817 * When this routine is finished, all settings and resources will be restored.
818 * Clients may not be, as they are actually restored by different processes.
820 *************************************<->***********************************/
823 RestoreResources( Boolean errorHandlerInstalled, ... )
826 int childStatus, execStatus, i;
832 * Check for alternate resource loader.
834 if ((pgrm = getenv("DTLOADRESOURCES")) == NULL)
836 pgrm = CDE_INSTALLATION_TOP "/bin/dtsession_res";
840 * By convention, exec() wants arg0 to be the program name. Ex: if pgrm
841 * is /usr/dt/bin/dtsession_res, the program name is dtsession_res.
842 * If all else fails, use pgrm.
844 argv[0] = (p = strrchr(pgrm, '/')) != NULL && *(p+1) != '\0' ? p+1 : pgrm;
847 Va_start(args,errorHandlerInstalled);
851 argv[i] = va_arg(args, char *);
857 * if an error handler is installed - remove it
859 if(errorHandlerInstalled)
861 sigaction(SIGCHLD, &smGD.defvec, (struct sigaction *) NULL);
865 * Fork and exec the xrdb process to load in the file created by
866 * writing out the resource manager string generated by the last
867 * session termination.
870 for(i = 0;(i < 10) && ((forkrc = vfork()) < 0);i++)
881 PrintErrnoError(DtError, smNLS.cantForkClientString);
886 * Fork succeeded - now do the exec
890 SetSIGPIPEToDefault ();
894 * Set the gid of the process back from bin
897 setregid(smGD.runningGID, smGD.runningGID);
899 setgid(smGD.runningGID);
900 setegid(smGD.runningGID);
903 #if defined(__osf__) || defined(CSRG_BASED)
909 MarkFileDescriptors (3, F_SETFD, 1);
911 execStatus = execv(pgrm, argv);
915 char clientMessage[MAXPATHLEN + 256];
917 memset(clientMessage, 0, MAXPATHLEN + 256);
918 snprintf(clientMessage, (MAXPATHLEN + 256) - 1,
919 ((char *)GETMESSAGE(16, 1, "Unable to exec process %s. No session resources will be restored.")), pgrm);
920 PrintErrnoError(DtError, clientMessage);
925 while(wait(&childStatus) != forkrc);
928 * if an error handler is installed - remove it
930 if(errorHandlerInstalled)
932 sigaction(SIGCHLD, &smGD.childvec, (struct sigaction *) NULL);
939 /*************************************<->*************************************
941 * RestorePreferences ( filename)
947 * This routine has two roles:
949 * 1) If 'filename' specified, the content of filename is read, and
950 * _DT_SM_PREFERENCES is populated with its content. This is used
951 * at session startup to set the initial state of _DT_SM_PREFERENCES.
953 * 2) If 'filename' is NULL, the content of _DT_SM_PREFERENCES is
954 * merged into RESOURCE_MANAGER. This is used when resources are
955 * reloaded at user request during a session.
968 *************************************<->***********************************/
980 struct stat statinfo;
982 if(access(filename,R_OK) != 0)
988 * Determine size of file.
990 if (stat(filename, &statinfo) == -1)
998 if ((data = (char *)SM_MALLOC(statinfo.st_size + 1)) == NULL)
1004 * Read file into memory.
1006 if ((fp = fopen(filename, "r")) == NULL)
1012 size = fread(data, 1, statinfo.st_size, fp);
1014 if (size == statinfo.st_size)
1017 * Merge .Xdefaults string into RESOURCE_MANAGER database, and
1018 * also convert to Xrm database form for later subtraction.
1021 _DtAddResString(smGD.display, data, _DT_ATR_PREFS);
1029 * Read string from _DT_SM_PREFERENCES
1031 data = _DtGetResString(smGD.display, _DT_ATR_PREFS);
1034 * Merge string into RESOURCE_MANAGER
1036 _DtAddResString(smGD.display, data, _DT_ATR_RESMGR);
1045 /*************************************<->*************************************
1047 * RestoreSettings ()
1052 * In charge of restoring all settings. Settings are stored in resource
1053 * format so it gets the values by getting the resource values stored in
1054 * a resource file that was created by the session manager.
1059 * smGD.settingPath = path that points to the settings resource file.
1068 * This routine messes with the actual strings returned by the resource
1069 * manager by tokenizing them, so these session settings resources should
1070 * not be accessed again.
1072 *************************************<->***********************************/
1074 RestoreSettings( void )
1076 XrmDatabase smBase = NULL;
1077 XKeyboardControl kbdControl;
1079 char **restorePtrArray, **tmpRestore;
1080 char *restoreCharArray;
1081 int numArgs, ptrSize, charSize;
1084 KeySym *tmpSyms, codeSym;
1087 XModifierKeymap restoreMod;
1091 restorePtrArray = (char **) SM_MALLOC (ptrSize * sizeof(char *));
1092 restoreCharArray = (char *) SM_MALLOC (charSize * sizeof(char));
1093 if((restorePtrArray == NULL) || (restoreCharArray == NULL))
1095 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1097 if(restorePtrArray != NULL)
1099 SM_FREE((char *) restorePtrArray);
1103 if(restoreCharArray != NULL)
1105 SM_FREE(restoreCharArray);
1112 * Load the resources from the SM database file
1114 if (smGD.settingPath[0] != 0)
1116 smBase = XrmGetFileDatabase(smGD.settingPath);
1120 PrintError(DtError, GETMESSAGE(16, 2, "Invalid client settings file. No settings restored."));
1125 XrmMergeDatabases(smBase, &(smGD.display->db));
1130 * Retrieve the session settings file from the database
1132 XtGetApplicationResources(smGD.topLevelWid, (XtPointer) &smSettings,
1133 settingsResources, XtNumber(settingsResources),
1137 * Copy any string resources since they may be overwritten in
1140 smGD.fontDirs = SmNewString(smSettings.fontDirs);
1141 smGD.autoRepeats = SmNewString(smSettings.autoRepeats);
1142 smGD.buttonMap = SmNewString(smSettings.buttonMap);
1143 smGD.keySyms = SmNewString(smSettings.keySyms);
1144 smGD.modSyms = SmNewString(smSettings.modSyms);
1148 * This is provided for backward compatibility sake. The values that
1149 * confirmMode can take have changed
1151 if(smSettings.confirmMode == DtSM_ASK_STATE)
1153 smSettings.confirmMode = DtSM_VERBOSE_MODE;
1157 * If the user has previously used the "query" method, and now wishes
1158 * to use "only what I've customized" method, then we have to start
1159 * from scratch. So don't set anything until customizer tells me to
1161 if((smSettings.didQuery == True) && (smRes.querySettings == False))
1163 SM_FREE((char *) restorePtrArray);
1164 SM_FREE(restoreCharArray);
1169 * Restore pointer control settings
1171 if((smSettings.accelNum > -1 ) || (smSettings.threshold > -1))
1173 XChangePointerControl(smGD.display, True, True,
1174 smSettings.accelNum,
1175 smSettings.accelDenom,
1176 smSettings.threshold);
1177 smToSet.pointerChange = True;
1181 smToSet.pointerChange = False;
1185 * Restore screen saver settings if any are set to non-default
1188 if ((smSettings.timeout > -1) || (smSettings.interval > -1) ||
1189 (smSaverRes.saverTimeout > -1) || (smSaverRes.lockTimeout > -1) ||
1190 (smSaverRes.cycleTimeout > -1))
1194 * For the time between Screen Savers, use the cycleTimeout
1195 * if the user has set this value. Otherwise, use the interval
1196 * value that was set when the session was saved.
1198 if (smSaverRes.cycleTimeout < 0)
1200 screenSaverVals.smInterval = smSettings.interval;
1204 screenSaverVals.smInterval = smSaverRes.cycleTimeout;
1208 * For the screen saver time, use the minimum of the values set for
1209 * saverTimeout or lockTimeout if the user has set one of these
1212 * Otherwise, use the Timeout value that was set when the
1213 * session was saved.
1215 * If it is not set, then use the minimum of the values set for
1216 * saverTimeout or lockTimeout. Set timeout to the Timeout value
1219 if ((smSaverRes.saverTimeout > -1) ||
1220 (smSaverRes.lockTimeout > -1))
1222 if (smSaverRes.saverTimeout > -1)
1224 if ((smSaverRes.lockTimeout > -1) &&
1225 (smSaverRes.lockTimeout < smSaverRes.saverTimeout))
1227 screenSaverVals.smTimeout = smSaverRes.lockTimeout;
1231 screenSaverVals.smTimeout = smSaverRes.saverTimeout;
1236 screenSaverVals.smTimeout = smSaverRes.lockTimeout;
1241 screenSaverVals.smTimeout = smSettings.timeout;
1243 screenSaverVals.smPreferBlank = smSettings.preferBlank;
1244 screenSaverVals.smAllowExp = smSettings.allowExp;
1246 /* Notify X of the new screen saver values */
1247 XSetScreenSaver(smGD.display, screenSaverVals.smTimeout,
1248 screenSaverVals.smInterval,
1249 screenSaverVals.smPreferBlank,
1250 screenSaverVals.smAllowExp);
1253 * If using timeout or interval values that were
1254 * previously saved, then set flag to indicate that they
1255 * should be saved again when the state for the session
1258 if ((smSettings.timeout > -1) || (smSettings.interval > -1))
1260 smToSet.screenSavChange = True;
1264 smToSet.screenSavChange = False;
1270 smToSet.screenSavChange = False;
1274 * Get the font path. Then set it.
1276 tmpRestore = restorePtrArray;
1278 *tmpRestore = strtok(smGD.fontDirs, ",");
1280 while(*tmpRestore != NULL)
1282 numArgs++; tmpRestore++;
1283 *tmpRestore = strtok(NULL, ",");
1284 if((numArgs >= ptrSize) && (*tmpRestore != NULL))
1287 restorePtrArray = (char **)SM_REALLOC((char *)
1288 restorePtrArray, ptrSize *
1290 if(restorePtrArray == NULL)
1292 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1293 SM_FREE(restoreCharArray);
1301 XSetFontPath(smGD.display, restorePtrArray, numArgs);
1305 * Restore the keyboard control information. In order for it
1306 * to be restored it has to be changed from a XKeyboardState
1307 * format to an XKeyboardControl format.
1309 if((smSettings.kbdState.key_click_percent > -1) ||
1310 (smSettings.kbdState.bell_percent > -1) ||
1311 (smSettings.kbdState.bell_pitch > -1) ||
1312 (smSettings.kbdState.bell_duration > -1))
1316 if((smSettings.kbdState.bell_percent > -1) ||
1317 (smSettings.kbdState.bell_pitch > -1) ||
1318 (smSettings.kbdState.bell_duration > -1))
1320 kbdControl.bell_percent = smSettings.kbdState.bell_percent;
1321 kbdControl.bell_pitch = smSettings.kbdState.bell_pitch;
1322 kbdControl.bell_duration = smSettings.kbdState.bell_duration;
1323 kbdControlMask |= (KBBellPercent | KBBellPitch | KBBellDuration);
1324 smToSet.audioChange = True;
1325 audioVals.smBellPercent = smSettings.kbdState.bell_percent;
1326 audioVals.smBellPitch = smSettings.kbdState.bell_pitch;
1327 audioVals.smBellDuration = smSettings.kbdState.bell_duration;
1331 smToSet.audioChange = False;
1334 if((smSettings.kbdState.key_click_percent > -1) ||
1335 (smSettings.kbdState.global_auto_repeat != AutoRepeatModeOn))
1337 kbdControl.key_click_percent =
1338 smSettings.kbdState.key_click_percent;
1339 kbdControlMask |= KBKeyClickPercent;
1340 smToSet.keyboardChange = True;
1341 keyboardVals.smKeyClickPercent = kbdControl.key_click_percent;
1345 smToSet.keyboardChange = False;
1350 * NOTICE THAT THE LED'S DON'T GET RESET. THIS IS BECAUSE LED STUFF
1351 * IS MACHINE DEPENDENT.
1354 * Set the auto repeat stuff
1356 tmpKey = strtok(smGD.autoRepeats, ",");
1357 if((tmpKey == NULL) &&
1358 ((smSettings.kbdState.global_auto_repeat == AutoRepeatModeOff) ||
1359 (smSettings.kbdState.global_auto_repeat == AutoRepeatModeOn)))
1361 smToSet.keyboardChange = True;
1362 kbdControl.auto_repeat_mode =
1363 smSettings.kbdState.global_auto_repeat;
1364 kbdControlMask |= KBAutoRepeatMode;
1365 XChangeKeyboardControl(smGD.display, kbdControlMask, &kbdControl);
1366 keyboardVals.smGlobalAutoRepeat =
1367 smSettings.kbdState.global_auto_repeat;
1373 smToSet.keyboardChange = True;
1374 kbdControl.auto_repeat_mode = smSettings.kbdState.global_auto_repeat;
1375 kbdControlMask |= KBAutoRepeatMode;
1376 XChangeKeyboardControl(smGD.display,
1377 kbdControlMask, &kbdControl);
1378 kbdControl.auto_repeat_mode = AutoRepeatModeOn;
1379 kbdControlMask = KBAutoRepeatMode | KBKey;
1381 * This is only involked when there is auto repeats set for
1382 * specific keys only. It is VERY SLOW code so unless you
1383 * have to save off auto repeats for single keys - DONT
1385 while(tmpKey != NULL)
1387 kbdControl.key = atoi(tmpKey);
1388 XChangeKeyboardControl(smGD.display,
1389 kbdControlMask, &kbdControl);
1390 tmpKey = strtok(NULL, ",");
1395 if(kbdControlMask != 0)
1397 XChangeKeyboardControl(smGD.display,
1398 kbdControlMask, &kbdControl);
1405 smToSet.audioChange = False;
1406 smToSet.keyboardChange = False;
1410 * Restore the button mappings
1413 tmpKey = strtok(smGD.buttonMap, ",");
1417 smToSet.pointerMapChange = True;
1421 smToSet.pointerMapChange = False;
1424 while(tmpKey != NULL)
1426 restoreCharArray[numArgs] = (char) atoi(tmpKey);
1428 tmpKey = strtok(NULL, ",");
1429 if((numArgs >= charSize) && (tmpKey != NULL))
1432 restoreCharArray = (char *) SM_REALLOC(restoreCharArray,
1433 charSize * sizeof(char));
1434 if(restoreCharArray == NULL)
1436 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1437 SM_FREE((char *)restorePtrArray);
1445 XSetPointerMapping(smGD.display, (unsigned char *)restoreCharArray, numArgs);
1448 * Copy the pointer map into the saved map for logout
1450 smToSet.numButton = ((numArgs > 5) ? 5 : numArgs);
1451 for(i = 0; i < smToSet.numButton;i++)
1453 smToSet.pointerMap[i] = restoreCharArray[i];
1458 * Restore the key mappings
1460 if(smSettings.numKeyCode > 0)
1462 tmpSyms = (KeySym *) restoreCharArray;
1463 symSize = (charSize * sizeof(char)) / sizeof(KeySym);
1464 tmpKey = strtok(smGD.keySyms, ",");
1465 for(i = 0;tmpKey != NULL;i++)
1467 tmpSyms[i] = (KeySym) atol(tmpKey);
1468 tmpKey = strtok(NULL, ",");
1470 if((numArgs >= symSize) && (tmpKey != NULL))
1473 symSize = (charSize * sizeof(char))/sizeof(KeySym);
1474 restoreCharArray = (char *) SM_REALLOC(restoreCharArray,
1475 (charSize * sizeof(char)));
1476 if(restoreCharArray == NULL)
1478 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
1479 SM_FREE((char *) restorePtrArray);
1482 tmpSyms = (KeySym *) restoreCharArray;
1485 numArgs /= smSettings.keySymPerCode;
1486 XChangeKeyboardMapping(smGD.display, (KeyCode)
1487 smGD.display->min_keycode,
1488 smSettings.keySymPerCode, tmpSyms,
1493 * Restore the modifier mappings
1495 tmpCode = (KeyCode *) restoreCharArray;
1496 tmpKey = strtok(smGD.modSyms, ",");
1499 for(i = 0;i < (8 * smSettings.maxKeyPerMod);i++)
1503 codeSym = (KeySym) atol(tmpKey);
1506 tmpCode[i] = XKeysymToKeycode(smGD.display, codeSym);
1510 tmpCode[i] = (KeyCode) 0;
1515 tmpCode[i] = (KeyCode) 0;
1517 tmpKey = strtok(NULL, ",");
1519 restoreMod.max_keypermod = smSettings.maxKeyPerMod;
1520 restoreMod.modifiermap = tmpCode;
1521 XSetModifierMapping(smGD.display, &restoreMod);
1524 SM_FREE((char *) restorePtrArray);
1525 SM_FREE(restoreCharArray);
1532 /*************************************<->*************************************
1534 * RestoreIndependentResources ()
1539 * In charge of restoring the resources that help make the session more
1540 * resolution and language independent - only restored if they are
1541 * necessary (lang || resolution has changed) and exist
1546 * smResources = global pointer to the resources to be restored by the SM
1556 *************************************<->***********************************/
1558 RestoreIndependentResources( void )
1562 unsigned long nitems, leftover;
1563 unsigned char *data = NULL;
1565 XrmValue fontResourceReturn;
1566 char *currentLangPtr, *resValRet, *sessionType;
1568 int intYRes[2], status,i;
1571 Boolean resIndep = False, resRet;
1574 if(((smGD.sessionLang == NULL) || (*smGD.sessionLang == 0)) &&
1575 (smRes.displayResolution == 0))
1578 * No saved info to draw from - nothing new is added
1583 currentLangPtr = getenv("LANG");
1585 fltYRes = ((float) DisplayHeight(smGD.display, 0) /
1586 (float) DisplayHeightMM(smGD.display, 0)) * 1000;
1588 if(fltYRes < MED_RES_Y_RES)
1590 intYRes[0] = LOW_RES_Y_RES;
1591 sessionRes = SM_LOW_RES_EXT;
1595 if(fltYRes >= HIGH_RES_Y_RES)
1597 intYRes[0] = HIGH_RES_Y_RES;
1598 sessionRes = SM_HIGH_RES_EXT;
1602 intYRes[0] = MED_RES_Y_RES;
1603 sessionRes = SM_MED_RES_EXT;
1607 if(smRes.displayResolution < MED_RES_Y_RES)
1609 intYRes[1] = LOW_RES_Y_RES;
1613 if(smRes.displayResolution >= HIGH_RES_Y_RES)
1615 intYRes[1] = HIGH_RES_Y_RES;
1619 intYRes[1] = MED_RES_Y_RES;
1624 * If the resolution or the language has changed -
1625 * load the language/resolution independent fonts if
1626 * they exist in the users home directory or in the system
1628 if((strcmp(currentLangPtr, smGD.sessionLang)) ||
1629 (intYRes[0] != intYRes[1]))
1631 char *fontPath = SM_MALLOC(MAXPATHLEN + 1);
1633 if(smGD.sessionType == HOME_SESSION)
1635 sessionType = SM_HOME_FONT_DIRECTORY;
1639 sessionType = SM_CURRENT_FONT_DIRECTORY;
1642 memset(fontPath, 0, MAXPATHLEN + 1);
1643 snprintf(fontPath, MAXPATHLEN, "%s/%s/%s/%s.%s",
1644 smGD.savePath, sessionType,
1645 currentLangPtr, SM_FONT_FILE, sessionRes);
1646 status = stat(fontPath, &buf);
1650 * User has nothing there - look in the system defaults
1651 * first in the language dep -then in lang independent
1653 memset(fontPath, 0, MAXPATHLEN + 1);
1655 if((currentLangPtr != NULL) && (*currentLangPtr != 0))
1657 strcat(fontPath, "/");
1658 strncat(fontPath, currentLangPtr, MAXPATHLEN);
1661 strncat(fontPath, "/", MAXPATHLEN);
1662 strncat(fontPath, SM_SYSTEM_FONT_FILE, MAXPATHLEN);
1666 status = stat(fontPath, &buf);
1669 if((currentLangPtr != NULL) && (*currentLangPtr != 0) &&
1670 (strcmp(currentLangPtr, "C")))
1672 memset(fontPath, 0, MAXPATHLEN + 1);
1673 strcpy(fontPath, "/C/");
1674 strncat(fontPath, SM_SYSTEM_FONT_FILE, MAXPATHLEN);
1678 status = stat(fontPath, &buf);
1695 strncpy(smGD.fontPath, fontPath, MAXPATHLEN);
1697 if(resIndep == True)
1701 * add the auxillary resources onto the root window
1703 RestoreResources(True, "-merge", "-file", smGD.fontPath, NULL);
1706 * Load the resources from the RESOURCE_MANAGER
1707 * property on the root window
1709 if(XGetWindowProperty(smGD.display, RootWindow(smGD.display, 0),
1710 XA_RESOURCE_MANAGER,0L,
1711 100000000L,False,XA_STRING,&actualType,
1712 &actualFormat,&nitems,&leftover,
1713 (unsigned char**) &data) == Success)
1715 smBase = XrmGetStringDatabase((char *)data);
1724 PrintError(DtError, GETMESSAGE(16, 6, "Invalid display/language independent resource file. No display/language independent resources will be restored."));
1725 SM_FREE((char *)data);
1731 * Get the new fontlist from the resources and
1732 * Put it on the application shell. Then add
1733 * the auxillary resources into the display struct
1735 resRet = XrmGetResource(smBase, "*fontList", "*FontList",
1736 &resValRet, &fontResourceReturn);
1739 XtSetArg(uiArgs[i], XmNdefaultFontList,
1740 (XmFontList) fontResourceReturn.addr);i++;
1741 XtSetValues(smGD.topLevelWid, uiArgs, i);
1744 * Overwrite the old font preferences, otherwise,
1745 * they'll come back to haunt us if the user logs in again
1746 * under the current language. We need to get the font
1747 * resources which have just been loaded, then overlay
1748 * them onto the _DT_SM_PREFERENCES root property to make
1749 * sure we get them back when we login again.
1751 for (i = 0; i < XtNumber(fonttype); i++)
1753 resRet = XrmGetResource(smBase, fonttype[i], fontclass[i],
1754 &resValRet, &fontResourceReturn);
1758 (char *)SM_MALLOC(fontResourceReturn.size + 30);
1759 bzero(resdata, fontResourceReturn.size + 30);
1760 strcat(resdata, fonttype[i]);
1761 strcat(resdata, ": ");
1762 strcat(resdata, fontResourceReturn.addr);
1763 strcat(resdata, "\n");
1764 _DtAddResString(smGD.display, resdata, _DT_ATR_PREFS);
1769 XrmMergeDatabases(smBase, &(smGD.display->db));
1770 SM_FREE((char *)data);
1774 SM_FREE((char*) fontPath);
1781 /*************************************<->*************************************
1788 * Reads through the client file and restores its contents. A client file
1789 * consists of hints for the workspace manager, actual client commands, and
1790 * remote execution commands. All commands are processed accordingly.
1791 * If this is the first DT 3.0 session for a DT 2.0 user then we will
1792 * also launch the helpviewer. If this is the first DT 3.0 session for a
1793 * DT 2.0 user then we will also run convertVS.sh to change all
1794 * occurances of /usr/bin/X11/hpterm to .../dt/bin/hpterm,
1795 * /usr/bin/X11/xterm to .../dt/bin/xterm and
1796 * /usr/bin/X11/xload to .../dt/bin/xload.
1807 * Any information read from the client file will be mucked with during
1808 * processing, and should not try to be mucked with again.
1810 * WARNING: This routine closes cfileP - not the calling routine
1811 * DOUBLE-WARNING: This routine starts the window manager
1813 *************************************<->***********************************/
1815 RestoreClients( void )
1817 unsigned char *lineP, *string;
1818 char *pch, *dispPtr = NULL;
1819 char *dispEnv, *dispSav, *dispEnvHelpview, *dispSavHelpview;
1820 unsigned char *hostPtr=NULL, *cmdPtr=NULL, *hintPtr = NULL;
1821 unsigned char *remoteDisplay;
1824 unsigned char tmpChar[35];
1825 int screenNum = 0, i, j, chlen, numClientsExec;
1826 int numRemoteDone = 0;
1828 Boolean clientsDone = False, wmHandshake = False, cmdInvInit = False;
1829 XClientMessageEvent smToWmMessage;
1832 * These variables are needed to buffer up the commands and then
1833 * execute them (also buffer up hints then put them on the root window
1835 unsigned char *hintsBuf[MAX_SCREENS_SAVED];
1836 unsigned char *cmdBuf[MAX_SCREENS_SAVED];
1837 unsigned int maxHintsSize[MAX_SCREENS_SAVED];
1838 unsigned int actHintsSize[MAX_SCREENS_SAVED];
1839 unsigned int numHints[MAX_SCREENS_SAVED];
1840 unsigned int maxCmdSize[MAX_SCREENS_SAVED];
1841 unsigned int actCmdSize[MAX_SCREENS_SAVED];
1842 unsigned int numCmd[MAX_SCREENS_SAVED];
1843 unsigned int maxRemoteSize[MAX_SCREENS_SAVED];
1846 * Initialize the buffers and their sizes to null and 0. Because of
1847 * all possible combinations - buffers aren't malloc'd until they're
1850 for(i = 0;i<smGD.numSavedScreens;i++)
1854 remoteBuf[i] = NULL;
1855 maxHintsSize[i] = 0;
1856 actHintsSize[i] = 0;
1861 maxRemoteSize[i] = 0;
1862 actRemoteSize[i] = 0;
1866 * Save the contents of the DISPLAY environment variable so that it
1867 * can be restored when we're through
1869 dispEnv = getenv(DISPLAY_NAME);
1872 dispSav = (char *) SM_MALLOC(((strlen(dispEnv) +
1873 strlen(DISPLAY_NAME_EQUAL)) * sizeof(char) + 1));
1874 sprintf(dispSav, "%s%s", DISPLAY_NAME_EQUAL, dispEnv);
1882 displayName = strdup(smGD.display->display_name);
1883 remoteDisplay = (unsigned char *)
1884 SM_MALLOC(sizeof(unsigned char) * (strlen(displayName) + 101));
1887 * Create the display name for locally executing clients
1913 * Create the display name for remotely executing clients.
1914 * These two may or may not be the same
1916 DtGetShortHostname((char *)remoteDisplay, 100);
1919 * Add the display qualifications to the host name
1920 * screen is added at execution time
1922 strcat((char *)remoteDisplay, (char *)dispPtr);
1925 * Intern the atom needed to put the hints on the root window
1926 * This has to be done here because InitProtocol has not been called yet
1928 XaWmDtHints = XInternAtom(smGD.display, _XA_DT_SESSION_HINTS, False);
1930 while(GetNextLine() != NULL)
1933 string = GetSmartString(&lineP);
1934 if( string != NULL && !strcmp((char *)string, "dtsmcmd"))
1936 while((string = GetSmartString(&lineP)) != NULL )
1938 if(!strcmp((char *)string, "-host"))
1941 * Extract a host pointer - host pointers
1942 * only exist on remote executions
1944 string = GetSmartString(&lineP);
1949 if(!strcmp((char *)string, "-cmd"))
1952 * Extract the command pointer from the
1955 string = GetSmartString(&lineP);
1960 if(!strcmp((char *)string, "-screen"))
1963 * Extract the screen number from the command
1965 string = GetSmartString(&lineP);
1966 screenNum = atoi((char *)string);
1971 if(!strcmp((char *)string, "-hints"))
1974 * Extract the hints string
1976 string = GetSmartString(&lineP);
1985 * Now put our information in buffers and reinitialize the pointers
1989 if(FillHintBuf(hintPtr, hintsBuf, maxHintsSize,
1990 actHintsSize, screenNum, numHints) != 0)
1993 * Free all malloc'd buffers and exit
1995 for(i = 0;i < smGD.numSavedScreens;i++)
1997 if(actHintsSize[i] > 0)
1999 SM_FREE((char *) hintsBuf[i]);
2001 if(actCmdSize[i] > 0)
2003 SM_FREE((char *) cmdBuf[i]);
2005 if(actRemoteSize[i] > 0)
2007 SM_FREE((char *) remoteBuf[i]);
2015 if((cmdPtr != NULL) && (hostPtr == NULL))
2017 if(FillCmdBuf(cmdPtr, cmdBuf, maxCmdSize,
2018 actCmdSize,screenNum, &numCmd[screenNum]) != 0)
2021 * Free all malloc'd buffers and exit
2023 for(i = 0;i < smGD.numSavedScreens;i++)
2025 if(actHintsSize[i] > 0)
2027 SM_FREE((char *) hintsBuf[i]);
2029 if(actCmdSize[i] > 0)
2031 SM_FREE((char *) cmdBuf[i]);
2033 if(actRemoteSize[i] > 0)
2035 SM_FREE((char *) remoteBuf[i]);
2044 if((cmdPtr != NULL) && (hostPtr != NULL))
2046 if(FillRemoteBuf(cmdPtr, hostPtr, remoteDisplay,
2047 remoteBuf, maxRemoteSize,
2048 actRemoteSize, screenNum) != 0)
2051 * Free all malloc'd buffers and exit
2053 for(i = 0;i < smGD.numSavedScreens;i++)
2055 if(actHintsSize[i] > 0)
2057 SM_FREE((char *) hintsBuf[i]);
2059 if(actCmdSize[i] > 0)
2061 SM_FREE((char *) cmdBuf[i]);
2063 if(actRemoteSize[i] > 0)
2065 SM_FREE((char *) remoteBuf[i]);
2074 screenNum = XDefaultScreen(smGD.display);
2079 * All done with file so close it off and set descriptor to NULL -
2080 * This is done so that parsing routines can be used with a buffer later
2086 * Now execute all the buffers, put all hints on the root windows
2087 * Do all remote executions
2089 for(i = 0;i < smGD.numSavedScreens;i++)
2092 * Put the root window property on each root window
2094 if(actHintsSize[i] > 0)
2097 * Append number of hints to front of buffer
2099 sprintf((char *)tmpChar, "%d", numHints[i]);
2100 strncpy((char *)hintsBuf[i], (char *)tmpChar,
2101 strlen((char *)tmpChar));
2102 XChangeProperty(smGD.display, RootWindow(smGD.display, i),
2103 XaWmDtHints, XA_STRING, 8, PropModeReplace,
2104 hintsBuf[i], actHintsSize[i]);
2105 SM_FREE((char *) hintsBuf[i]);
2106 XSync(smGD.display, 0);
2114 * Now exec on the local clients - we're doing contention management
2115 * to make sure the system doesn't get swamped
2119 while((actCmdSize[i] == 0) && (i < smGD.numSavedScreens))
2124 envVal = SM_MALLOC(BUFSIZ);
2125 if(i >= smGD.numSavedScreens)
2131 sprintf(envVal,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, i);
2139 * Keep forking one client after the other until the
2140 * memory utilization gets beyond the threshold -
2141 * (but only if the capability exists) Then go to
2142 * window manager handshaking
2144 #ifdef DEBUG_CONT_MANAGEMENT
2145 if(smRes.contManagement & SM_CM_SYSTEM)
2147 fprintf(stderr, "SM_CM_SYSTEM flag set in smRes.contManagement\n");
2149 if(smRes.contManagement & SM_CM_HANDSHAKE)
2151 fprintf(stderr, "SM_CM_HANDSHAKE flag set in smRes.contManagement\n");
2153 #endif /* DEBUG_CONT */
2155 if((smRes.contManagement & SM_CM_SYSTEM) &&
2156 ((GetMemoryUtilization() != MEM_NOT_AVAILABLE) &&
2157 (clientsDone == False)))
2159 while((GetMemoryUtilization() == MEM_NOT_FULL) &&
2160 (clientsDone == False))
2164 CreateExecString((char *) lineP);
2165 if(smExecArray[0] != NULL)
2167 (void) StartClient(smExecArray[0], (char **)smExecArray, NULL,
2168 NULL, NULL, False, False, -1);
2173 * When all the clients have been exec'd for this screen
2176 if(numClientsExec >= numCmd[i])
2178 ResetScreenInfo(cmdBuf, &i, actCmdSize, &clientsDone,
2179 envVal, displayName);
2186 * After we've checked memory utilization - finish up
2187 * by handshaking with the worksapce manager - if it's there
2189 if(clientsDone == False)
2191 if((smGD.dtwmRunning) && (smRes.contManagement & SM_CM_HANDSHAKE))
2194 * Get the window id of the workspace manager and tell it
2195 * to start messaging
2197 _DtGetMwmWindow(smGD.display, RootWindow(smGD.display, 0),
2199 smToWmMessage.type = ClientMessage;
2200 smToWmMessage.window = dtwmWin;
2201 smToWmMessage.message_type = XaSmWmProtocol;
2202 smToWmMessage.format = 32;
2203 smToWmMessage.data.l[0] = XaSmStartAckWindow;
2204 smToWmMessage.data.l[1] = CurrentTime;
2205 if (XSendEvent(smGD.display, dtwmWin,False,NoEventMask,
2206 (XEvent *) &smToWmMessage) != 0)
2209 XSync(smGD.display, 0);
2215 * Start a client - and wait for the workspace manager to
2216 * map a window to start a new client
2218 while(clientsDone == False)
2222 CreateExecString((char *) lineP);
2223 if(smExecArray[0] != NULL)
2225 (void) StartClient(smExecArray[0], smExecArray,
2226 NULL, NULL, NULL, False, False, -1);
2230 * If we're handshaking with the workspace manager
2231 * wait for the client to be mapped before starting
2234 if(wmHandshake == True)
2242 * When all the clients have been exec'd for this screen
2245 if(numClientsExec >= numCmd[i])
2247 ResetScreenInfo(cmdBuf, &i, actCmdSize, &clientsDone,
2248 envVal, displayName);
2253 if(wmHandshake == True)
2256 * If we are handshaking - tell the workspace manager to
2259 smToWmMessage.type = ClientMessage;
2260 smToWmMessage.window = dtwmWin;
2261 smToWmMessage.message_type = XaSmWmProtocol;
2262 smToWmMessage.format = 32;
2263 smToWmMessage.data.l[0] = XaSmStopAckWindow;
2264 smToWmMessage.data.l[0] = CurrentTime;
2265 XSendEvent(smGD.display, dtwmWin,False,NoEventMask,
2266 (XEvent *) &smToWmMessage);
2271 for(i = 0;i < smGD.numSavedScreens;i++)
2273 if(numRemoteDone == MAX_REMOTE_CLIENTS)
2279 * Send out all the remote execution commands for the screen to
2280 * the command invoker. On failure - do a remsh instead
2282 if(actRemoteSize[i] > 0)
2285 * Initialize the command invoker - if not done
2287 if(cmdInvInit == False)
2289 _DtInitializeCommandInvoker(smGD.display,
2297 * Set up the display environment variable so that the
2298 * application comes back to the right screen
2300 sprintf(envVal,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, i);
2304 parseP = remoteBuf[i];
2305 while(numRemoteExecs > 0 && GetNextLine() != NULL)
2308 * Get the host and the command and send them off
2309 * On failure of the command invoker do a remsh
2312 string = GetSmartString(&lineP);
2314 string = GetSmartString(&lineP);
2317 remoteBufPtr[numRemoteDone].cmdPtr = cmdPtr;
2318 remoteBufPtr[numRemoteDone].hostPtr = hostPtr;
2320 _DtCommandInvokerExecute(DtSTART_SESSION, NULL, NULL, NULL,
2321 "-", (char *) hostPtr, (char *) cmdPtr,
2322 RemoteRequestSucceeded, NULL,
2323 RemoteRequestFailed,
2324 &remoteBufPtr[numRemoteDone]);
2328 * If there is no more room in the remote client
2329 * array - quit exec'ing remote clients
2331 if(numRemoteDone == MAX_REMOTE_CLIENTS)
2333 PrintError(DtError, GETMESSAGE(16, 5, "You have reached the maximum allowed number of remote clients. No further remote clients will be restored."));
2343 * Now return the display variable back to the display that was
2344 * originally opened (the default display)
2352 FixEnvironmentData();
2357 } /* END OF FUNCTION RestoreClients */
2361 /*************************************<->*************************************
2363 * StartEtc ( exiting )
2368 * Call the StartClient routine to fork and exec either the sessionetc file
2369 * (if exiting==False) or the sessionexit file (if exiting==True).
2381 *************************************<->***********************************/
2383 StartEtc( Boolean exiting )
2390 execArray[0] = smGD.exitPath;
2391 execArray[1] = smExitFile;
2393 execArray[0] = smGD.etcPath;
2394 execArray[1] = smEtcFile;
2396 execArray[2] = '\0';
2398 if ((status=stat(execArray[0], &buf)) != -1)
2400 StartClient(execArray[0], execArray, NULL, NULL, NULL, False, False, -1);
2405 /*************************************<->*************************************
2412 * Returns the next line from an fopened configuration file or a newline-
2413 * embedded configuration string.
2418 * cfileP = (global) file pointer to fopened configuration file or NULL
2419 * line = (global) line buffer
2420 * linec = (global) line count
2421 * parseP = (global) parse string pointer if cfileP == NULL
2426 * line = (global) next line
2427 * linec = (global) line count incremented
2428 * parseP = (global) parse string pointer incremented
2429 * Return = line or NULL if file or string is exhausted.
2434 * If there are more than MAXLINE characters on a line in the file cfileP the
2435 * excess are truncated.
2436 * Assumes the line buffer is long enough for any parse string line.
2437 * Code stolen from dtmwm
2439 *************************************<->***********************************/
2440 static unsigned char *
2443 unsigned char *string;
2449 /* read fopened file */
2451 string = (unsigned char *) fgets((char *)line, fileSize, cfileP);
2453 else if ((parseP != NULL) && (*parseP != 0))
2454 /* read parse string */
2458 while ((*parseP != 0) &&
2459 ((chlen = mblen ((char *) parseP, MB_CUR_MAX)) > 0) &&
2461 /* copy all but NULL and newlines to line buffer */
2465 *(string++) = *(parseP++);
2469 while ((*parseP != NULL) && (*parseP != '\n'))
2470 /* copy all but NULL and newlines to line buffer */
2472 *(string++) = *(parseP++);
2476 if (*parseP == '\n')
2489 } /* END OF FUNCTION GetNextLine */
2493 /*************************************<->*************************************
2495 * PeekAhead (currentChar, currentLev)
2500 * Returns a new level value if this is a new nesting level of quoted string
2501 * Otherwise it returns a zero
2506 * currentChar = current position in the string
2507 * currentLev = current level of nesting
2512 * Returns either a new level of nesting or zero if the character is copied in
2518 *************************************<->***********************************/
2521 unsigned char *currentChar,
2522 unsigned int currentLev )
2524 Boolean done = False;
2525 unsigned int tmpLev = 1;
2529 while (((chlen = mblen ((char *) currentChar, MB_CUR_MAX)) > 0) &&
2530 (chlen == 1) && ((*currentChar == '"') || (*currentChar == '\\'))
2535 if(((chlen = mblen ((char *) currentChar, MB_CUR_MAX)) > 0) && (chlen == 1) &&
2536 ((*currentChar == '"') || (*currentChar == '\\')))
2539 if(*currentChar == '"')
2550 while((*currentChar != NULL) && (done == False) &&
2551 ((*currentChar == '"') || (*currentChar == '\\')))
2554 if((*currentChar != NULL) &&
2555 ((*currentChar == '"') || (*currentChar == '\\')))
2558 if(*currentChar == '"')
2568 #endif /*MULTIBYTE*/
2571 * Figure out if this is truly a new level of nesting - else ignore it
2572 * This section probably could do some error checking and return -1
2573 * If so, change type of routine from unsigned int to int
2587 /*************************************<->*************************************
2589 * GetSmartString (linePP)
2594 * Returns the next quoted or whitespace-terminated nonquoted string in the
2596 * Additional functionality added to GetString in that anything in a
2597 * quoted string is considered sacred and nothing will be stripped from
2598 * the middle of a quoted string.
2603 * linePP = pointer to current line buffer pointer.
2608 * linePP = pointer to revised line buffer pointer.
2614 * May alter the line buffer contents.
2615 * Handles quoted strings and characters, removing trailing whitespace from
2617 * Returns NULL string if the line is empty or is a comment.
2618 * Code stolen from dtmwm.
2620 *************************************<->***********************************/
2622 static unsigned char *
2624 unsigned char **linePP )
2626 unsigned char *lineP = *linePP;
2627 unsigned char *endP;
2628 unsigned char *curP;
2629 unsigned char *lnwsP;
2630 unsigned int level = 0, checkLev, i, quoteLevel[MAX_QUOTE_DEPTH];
2634 /* get rid of leading white space */
2635 ScanWhitespace (&lineP);
2638 * Return NULL if line is empty, whitespace, or begins with a comment.
2640 if((chlen = mblen ((char *) lineP, MB_CUR_MAX)) < 1)
2646 if ((chlen == 1) && (*lineP == '"'))
2649 quoteLevel[level] = 1;
2651 * Start beyond double quote and find the end of the quoted string.
2652 * '\' quotes the next character - but is not stripped out.
2653 * Otherwise, matching double quote or NULL terminates the string.
2655 * We use lnwsP to point to the last non-whitespace character in the
2656 * quoted string. When we have found the end of the quoted string,
2657 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
2658 * This removes any trailing whitespace without overwriting the
2659 * matching quote, needed later. If the quoted string was all
2660 * whitespace, then this will write a NULL at the beginning of the
2661 * string that will be returned -- OK.
2663 lnwsP = lineP++; /* lnwsP points to first '"' */
2664 curP = endP = lineP; /* other pointers point beyond */
2666 while ((*endP = *curP) &&
2667 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0) &&
2668 ((chlen > 1) || (*curP != '"')))
2669 /* Haven't found matching quote yet.
2670 * First byte of next character has been copied to endP.
2674 if ((chlen == 1) && (*endP == '\\') &&
2675 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0))
2678 * Check to see if this is a quoted quote - if it is
2679 * strip off a level - if not - it's sacred leave it alone
2681 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
2684 if(quoteLevel[level] >= checkLev)
2686 if (level > 0) level--;
2688 else if (level < MAX_QUOTE_DEPTH)
2691 quoteLevel[level] = checkLev;
2694 for(i = 0;i < (checkLev - 2);i++)
2696 *endP++ = *curP++;curP++;
2703 /* Singlebyte character: character copy finished. */
2705 if (isspace (*endP))
2706 /* whitespace character: leave lnwsP unchanged. */
2711 /* non-whitespace character: point lnwsP to it. */
2717 /* Multibyte (nonwhitespace) character: point lnwsP to it.
2718 * Finish character byte copy.
2731 /* get rid of leading white space */
2732 ScanWhitespace (&lineP);
2734 /* Return NULL if line is empty, or whitespace */
2744 quoteLevel[level] = 1;
2746 * Start beyond double quote and find the end of the quoted string.
2747 * '\' quotes the next character.
2748 * Otherwise, matching double quote or NULL terminates the string.
2750 * We use lnwsP to point to the last non-whitespace character in the
2751 * quoted string. When we have found the end of the quoted string,
2752 * increment lnwsP and if lnwsP < endP, write NULL into *lnwsP.
2753 * This removes any trailing whitespace without overwriting the
2754 * matching quote, needed later. If the quoted string was all
2755 * whitespace, then this will write a NULL at the beginning of the
2756 * string that will be returned -- OK.
2758 lnwsP = lineP++; /* lnwsP points to first '"' */
2759 curP = endP = lineP; /* other pointers point beyond */
2761 while ((*endP = *curP) && (*endP != '"'))
2762 /* haven't found matching quote yet */
2764 /* point curP to next character */
2766 if ((*endP == '\\') && (*curP != NULL))
2767 /* shift quoted nonNULL character down and curP ahead */
2770 * Check to see if this is a quoted quote - if it is
2771 * strip off a level - if not - it's sacred leave it alone
2773 checkLev = PeekAhead((curP - 1), quoteLevel[level]);
2776 if(quoteLevel[level] >= checkLev)
2778 if (level > 0) level--;
2780 else if (level < MAX_QUOTE_DEPTH)
2783 quoteLevel[level] = checkLev;
2786 for(i = 0;i < (checkLev - 2);i++)
2788 *endP++ = *curP++;curP++;
2794 if (isspace (*endP))
2795 /* whitespace character: leave lnwsP unchanged. */
2800 /* non-whitespace character: point lnwsP to it. */
2808 * Found matching quote or NULL.
2809 * NULL out any trailing whitespace.
2820 /* Unquoted string */
2823 * Find the end of the nonquoted string.
2824 * '\' quotes the next character.
2825 * Otherwise, whitespace, NULL, terminates the string.
2827 curP = endP = lineP;
2830 while ((*endP = *curP) &&
2831 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0) &&
2832 ((chlen > 1) || (!isspace (*curP))))
2833 /* Haven't found whitespace yet.
2834 * First byte of next character has been copied to endP.
2838 if ((chlen == 1) && (*endP == '\\') &&
2839 ((chlen = mblen ((char *) curP, MB_CUR_MAX)) > 0))
2841 * copy first byte of quoted nonNULL character down.
2842 * point curP to next byte
2849 /* Multibyte character: finish character copy. */
2858 while ((*endP = *curP) && !isspace (*endP))
2860 /* point curP to next character */
2862 if ((*endP == '\\') && (*curP != NULL))
2863 /* shift quoted nonNULL character down and curP ahead */
2873 * Two cases for *endP:
2875 * matching quote -> write NULL over char and point beyond
2876 * NULL -> point to NULL
2881 *endP = 0; /* write NULL over terminator */
2882 *linePP = ++curP; /* point beyond terminator */
2888 return ((unsigned char *)lineP);
2890 } /* END OF FUNCTION GetString */
2895 /*************************************<->*************************************
2897 * ScanWhitespace(linePP)
2902 * Scan the string, skipping over all white space characters.
2907 * linePP = nonNULL pointer to current line buffer pointer
2912 * linePP = nonNULL pointer to revised line buffer pointer
2917 * Assumes linePP is nonNULL
2918 * Code Stolen from dtmwm
2920 *************************************<->***********************************/
2923 unsigned char **linePP )
2926 while (*linePP && (mblen ((char *) *linePP, MB_CUR_MAX) == 1) && isspace (**linePP))
2928 while (*linePP && isspace (**linePP))
2934 } /* END OF FUNCTION ScanWhitespace */
2938 /*************************************<->*************************************
2940 * FillHintBuf(newHint, hintBuf, maxSize, actSize, screen, numHints)
2945 * Put the new hint into the hint buffer. Each hint is separated by a
2951 * newHint = hint to add to the buffer
2952 * hintBuf = an array of buffers - one for each screen
2953 * maxSize = array of buffers of the current malloced size of each hintBuf
2954 * actSize = array of space currently used by each hintBuf
2955 * screen = screen number for this hint
2956 * numHints = array of the number of hints for each screen
2957 * smGD.numSavedScreens = (global) checked to make sure this hint should be
2962 * hintBuf[screen] = updated hint buf for this screen (newHint added)
2963 * maxSize[screen] = enlarged if not big enough or malloced if not done before
2964 * actSize[screen] = updated size of the hints buffer
2965 * numHints[screen] = updated by 1 if this hint is added
2971 *************************************<->***********************************/
2974 unsigned char *newHint,
2975 unsigned char **hintBuf,
2976 unsigned int *maxSize,
2977 unsigned int *actSize,
2978 unsigned int screen,
2979 unsigned int *numHints)
2981 static int hintBufSize = 5000;
2984 * If the screen that this hint was meant for is not in the current
2985 * set of available screens, don't save it
2987 if(screen >= smGD.numSavedScreens)
2993 * Check to see if this buffer has been malloc'd before - if it hasn't
2994 * malloc it. If it has - check to make sure it's big enough to hold the
2997 if(maxSize[screen] == 0)
2999 hintBuf[screen] = (unsigned char *) SM_MALLOC(hintBufSize * sizeof(char));
3000 if(hintBuf[screen] == NULL)
3002 actSize[screen] = 0;
3003 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3006 maxSize[screen] = hintBufSize * sizeof(char);
3009 * Now reserve 4 bytes for the length
3011 strcpy((char *)hintBuf[screen], " \n");
3015 if((actSize[screen] + strlen((char *)newHint) + 2) >= maxSize[screen])
3017 hintBuf[screen] = (unsigned char *)
3018 SM_REALLOC((char *) hintBuf[screen],
3022 if(hintBuf[screen] == NULL)
3024 actSize[screen] = 0;
3025 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3028 maxSize[screen] = maxSize[screen] + (hintBufSize * sizeof(char));
3033 * add the new hint AFTER the last newline
3035 strcat((char *)hintBuf[screen], (char *)newHint);
3036 strcat((char *)hintBuf[screen], "\n");
3037 actSize[screen] = strlen((char *)hintBuf[screen]);
3038 numHints[screen] += 1;
3045 /*************************************<->*************************************
3047 * FillCmdBuf(newCmd, cmdBuf, maxSize, actSize, screen)
3052 * Put a new command into the command buffer. The command buffer is just
3053 * one big long string of stuff to be executed.
3058 * newCmd = command to add to the buffer
3059 * cmdBuf = an array of buffers - one for each screen
3060 * maxSize = array of buffers of the current malloced size of each cmdBuf
3061 * actSize = array of space currently used by each cmdBuf
3062 * screen = screen number for this command
3063 * smGD.numSavedScreens = (global) checked to make sure this hint should be
3068 * cmdBuf[screen] = updated command buf for this screen (newCmd added)
3069 * maxSize[screen] = enlarged if not big enough or malloced if not done before
3070 * actSize[screen] = updated size of the command buffer
3076 *************************************<->***********************************/
3079 unsigned char *newCmd,
3080 unsigned char **cmdBuf,
3081 unsigned int *maxSize,
3082 unsigned int *actSize,
3083 unsigned int screen,
3084 unsigned int *numCmd )
3086 static int cmdBufSize = 5000;
3089 * If the screen that this command was meant for is not in the current
3090 * set of available screens, don't save it
3092 if(screen >= smGD.numSavedScreens)
3098 * Check to see if this buffer has been malloc'd before - if it hasn't
3099 * malloc it. If it has - check to make sure it's big enough to hold the
3102 if(maxSize[screen] == 0)
3104 cmdBuf[screen] = (unsigned char *) SM_MALLOC(cmdBufSize * sizeof(char));
3105 if(cmdBuf[screen] == NULL)
3107 actSize[screen] = 0;
3108 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3111 maxSize[screen] = cmdBufSize * sizeof(char);
3115 if((actSize[screen] + strlen((char *)newCmd)) >= maxSize[screen])
3117 cmdBuf[screen] = (unsigned char *) SM_REALLOC((char *)cmdBuf[screen],
3121 if(cmdBuf[screen] == NULL)
3123 actSize[screen] = 0;
3124 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3127 maxSize[screen] = maxSize[screen] + (cmdBufSize * sizeof(char));
3131 if(actSize[screen] == 0)
3133 strcpy((char *)cmdBuf[screen], (char *)newCmd);
3137 strcat((char *)cmdBuf[screen], (char *)newCmd);
3140 *numCmd = *numCmd + 1;
3141 strcat((char *)cmdBuf[screen], "\n");
3142 actSize[screen] = strlen((char *)cmdBuf[screen]);
3149 /*************************************<->*************************************
3151 * FillRemoteBuf(newCmd, hostName, displayName, remoteBuf,
3152 * maxSize, actSize, screen)
3157 * Put a new command into the remote execution buffer. The command buffer is
3158 * just one big long string of stuff to be executed.
3163 * newCmd = command to add to the buffer
3164 * hostName = host where command is to be executed from
3165 * displayName = display where host is to be executed to
3166 * remoteBuf = an array of buffers - one for each screen
3167 * maxSize = array of buffers of the current malloced size of each cmdBuf
3168 * actSize = array of space currently used by each cmdBuf
3169 * screen = screen number for this command
3170 * smGD.numSavedScreens = (global) checked to make sure this hint should be
3175 * cmdBuf[screen] = updated command buf for this screen (newCmd added)
3176 * in remote format (host name and display name)
3177 * maxSize[screen] = enlarged if not big enough or malloced if not done before
3178 * actSize[screen] = updated size of the command buffer
3184 *************************************<->***********************************/
3187 unsigned char *newCmd,
3188 unsigned char *hostName,
3189 unsigned char *displayName,
3190 unsigned char *remoteBuf[] ,
3191 unsigned int *maxSize ,
3192 unsigned int *actSize ,
3193 unsigned int screen )
3195 unsigned char *string;
3196 static int remoteBufSize = 5000;
3199 * If the screen that this command was meant for is not in the current
3200 * set of available screens, don't save it
3202 if(screen >= smGD.numSavedScreens)
3208 * Check to see if this buffer has been malloc'd before - if it hasn't
3209 * malloc it. If it has - check to make sure it's big enough to hold the
3212 if(maxSize[screen] == 0)
3214 remoteBuf[screen] = (unsigned char *)
3215 SM_MALLOC(remoteBufSize * sizeof(char));
3216 if(remoteBuf[screen] == NULL)
3218 actSize[screen] = 0;
3219 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3222 maxSize[screen] = remoteBufSize * sizeof(char);
3226 if((actSize[screen] + strlen((char *)newCmd) +
3227 strlen((char *)hostName) +
3228 strlen((char *)displayName) +
3229 strlen("-display ") + 5) >= maxSize[screen])
3231 remoteBuf[screen] = (unsigned char *)
3232 SM_REALLOC((char *)remoteBuf[screen],
3234 (remoteBufSize * sizeof(char)));
3235 if(remoteBuf[screen] == NULL)
3237 actSize[screen] = 0;
3238 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
3241 maxSize[screen] = maxSize[screen] + (remoteBufSize * sizeof(char));
3245 if(actSize[screen] == 0)
3248 * If the buffer is empty fill it with the initial contents
3250 strcpy((char *)remoteBuf[screen], (char *)hostName);
3251 strcat((char *)remoteBuf[screen], " ");
3256 * if this buffer is not emtpy
3257 * add the new command BEFORE the last null terminator
3258 * Commands for remote executions are separated by newlines
3260 strcat((char *)remoteBuf[screen], "\n");
3261 strcat((char *)remoteBuf[screen], (char *)hostName);
3265 * Copy the command in - quote it
3267 strcat((char *)remoteBuf[screen], " \"");
3268 string = GetSmartString(&newCmd);
3269 strcat((char *)remoteBuf[screen], (char *)string);
3270 strcat((char *)remoteBuf[screen], " ");
3273 * Once display name has been put in place - concatenate the
3274 * rest of the command
3276 while((string = GetSmartString(&newCmd)) != NULL )
3278 strcat((char *)remoteBuf[screen], " ");
3279 strcat((char *)remoteBuf[screen], (char *)string);
3283 * Now close off the command with a quote
3285 strcat((char *)remoteBuf[screen], "\"");
3287 actSize[screen] = strlen((char *)remoteBuf[screen]);
3290 * Bump the remote command counter
3298 /*************************************<->*************************************
3300 * CreateExecString(execString)
3305 * Create a string that can be fed to a fork and exec by breaking it up
3306 * into argc and argv
3311 * execString = whole command
3315 * smExecArray = global modified to contain pointers to argc and argv
3321 *************************************<->***********************************/
3329 static int iSizeArgv = ARG_AMT;
3334 if (smExecArray == NULL)
3336 smExecArray = (char **) XtMalloc (ARG_AMT * sizeof(char *));
3338 string = (char *) GetSmartString((unsigned char **) &execString);
3339 while(string != NULL)
3341 smExecArray[argc] = string;
3343 if (argc >= iSizeArgv)
3345 iSizeArgv += ARG_AMT;
3346 smExecArray = (char **)
3347 XtRealloc ((char *)smExecArray, (iSizeArgv * sizeof(char *)));
3349 string = (char *) GetSmartString((unsigned char **) &execString);
3353 * If the last string is a background character
3358 if(!strcmp((char *)smExecArray[argc - 1], "&"))
3360 smExecArray[argc - 1] = '\0';
3364 smExecArray[argc] = '\0';
3366 } /* END OF FUNCTION CreateExecString */
3370 * SetTemporaryDisplay - does a putenv of the current value of the
3371 * DISPLAY environment variable but with the given screen number.
3377 SetTemporaryDisplay (
3380 static char * tmpDisplay = NULL;
3381 static int lastScreen = -1;
3384 if (screenNum == -1)
3387 if (!savedDisplay) {
3390 if ((dispEnv = getenv (DISPLAY_NAME)) == NULL)
3392 savedDisplay = XtMalloc (strlen (DISPLAY_NAME_EQUAL) +
3393 strlen (dispEnv) + 2);
3396 sprintf (savedDisplay, "%s%s", DISPLAY_NAME_EQUAL, dispEnv);
3399 if (lastScreen == screenNum && tmpDisplay != NULL) {
3400 putenv (tmpDisplay);
3403 lastScreen = screenNum;
3408 tmpDisplay = XtMalloc (strlen (savedDisplay) + 4);
3411 strcpy (tmpDisplay, savedDisplay);
3414 if (pch = strrchr (tmpDisplay, ':')) {
3417 if (pch2 = strchr (pch, '.'))
3419 pch3 = XtMalloc (strlen (tmpDisplay) + 4);
3422 sprintf (pch3, "%s.%d", tmpDisplay, screenNum);
3423 strcpy (tmpDisplay, pch3);
3424 XtFree ((char *) pch3);
3426 putenv (tmpDisplay);
3432 * RestoreDisplay - does a putenv of the global variable savedDisplay
3438 if (screenNum != -1 && savedDisplay)
3439 putenv (savedDisplay);
3443 /*************************************<->*************************************
3445 * StartClient - calls StartLocalClient or StartRemoteClient depending
3446 * on the value of hostName.
3450 * Starts a local or remote application
3454 * program = execArray[0]
3455 * execArray = command to fork and exec
3456 * hostName = the name of the host where program should be executed
3457 * cwd = directory to chdir to before doing the exec
3458 * envp = the envrironment variables to add to the child processes env
3459 * checkCwd = if True and cwd is NULL, a message will be logged; if
3460 * False, cwd will not be checked and the cwd will be set to $HOME
3461 * useIgnoreEnvironmentResource = if True, the variables listed in the
3462 * IgnoreEnvironment resource will be removed from 'environ' before
3463 * execArray is exec'd
3464 * screen = if set to -1, it will be ignored; otherwise, the screen
3465 * number will be used to define DISPLAY for the duration of this
3466 * function - DISPLAY will be reset before the function returns.
3470 * Returns True if the command is successfully executed; False otherwise.
3474 * localHost - is modified
3476 *************************************<->***********************************/
3485 Boolean useIgnoreEnvironmentResource,
3488 static char * defaultCwd = NULL;
3489 Boolean cwdNull = False;
3490 Boolean startStatus;
3492 SetTemporaryDisplay (screen);
3494 if (!ignoreEnvPtr && useIgnoreEnvironmentResource) {
3495 if (smRes.ignoreEnvironment)
3496 ignoreEnvPtr = _DtVectorizeInPlace (
3497 smRes.ignoreEnvironment, ',');
3501 if (getenv ("HOME"))
3502 defaultCwd = strdup (getenv ("HOME"));
3504 defaultCwd = getcwd (NULL, MAXPATHLEN + 1);
3506 (void) gethostname (localHost, MAXHOSTNAMELEN);
3514 if (!hostName || (_DtIsSameHost (localHost, hostName)))
3515 startStatus = StartLocalClient (program, execArray,
3516 cwd, envp, checkCwd,
3517 useIgnoreEnvironmentResource);
3519 startStatus = StartRemoteClient (program, execArray, hostName,
3521 useIgnoreEnvironmentResource);
3523 RestoreDisplay (screen);
3525 return (startStatus);
3528 /*************************************<->*************************************
3534 * Starts a local application.
3537 * Returns True if the command is successfully executed; False otherwise.
3539 *************************************<->***********************************/
3547 Boolean useIgnoreEnvironmentResource)
3551 char clientMessage[MAXPATHLEN + 30];
3552 char **tmpEnv, **ppchar;
3555 * Fork and exec the client process
3557 clientFork = vfork();
3560 * If the fork fails - Send out an error and return
3564 PrintErrnoError(DtError, smNLS.cantForkClientString);
3569 * Fork succeeded - now do the exec
3573 SetSIGPIPEToDefault ();
3576 * Log a warning if the given cwd is not valid
3580 if ((chdir (cwd)) == -1)
3584 tmpCwd = getcwd (NULL, MAXPATHLEN + 1);
3586 LogCWDMessage (cwd, program, tmpCwd);
3591 * Add envp to the client's environ if the variable
3592 * is not in the ignoreEnvironment list
3594 if (useIgnoreEnvironmentResource && envp) {
3597 tmpEnv = RemoveEnvironmentVars (envp);
3601 for (ppchar = tmpEnv; ppchar && *ppchar; ppchar++)
3602 putenv (strdup (*ppchar));
3607 * Set the gid of the process back from bin
3610 setregid(smGD.runningGID, smGD.runningGID);
3612 setgid(smGD.runningGID);
3613 setegid(smGD.runningGID);
3617 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3619 #if defined(__osf__) || defined(CSRG_BASED)
3623 #endif /* __osf__ */
3625 MarkFileDescriptors (3, F_SETFD, 1);
3627 execStatus = execvp(program, execArray);
3630 sprintf(clientMessage, ((char *)GETMESSAGE(16, 3, "Unable to exec %s.")), execArray[0]);
3631 PrintErrnoError(DtError, clientMessage);
3639 /*************************************<->*************************************
3645 * Starts a remote application.
3648 * Returns True if the command is successfully executed; False otherwise.
3650 *************************************<->***********************************/
3658 Boolean useIgnoreEnvironmentResource)
3661 SPC_Channel_Ptr channel;
3663 char errorMessage[1024];
3665 static Boolean cmdInvokerInitialized = False;
3666 char ** tmpEnv = envp;
3668 ioMode = SPCIO_NOIO | SPCIO_FORCE_CONTEXT;
3670 if (!cmdInvokerInitialized) {
3671 _DtInitializeCommandInvoker(smGD.display,
3675 cmdInvokerInitialized = True;
3678 (void) strcpy (errorMessage, "");
3680 channel = (SPC_Channel_Ptr) _DtSPCOpen (hostName, ioMode, errorMessage);
3681 if (channel == SPC_ERROR) {
3682 message = strdup ((char *) GETMESSAGE (40, 13,
3683 "The following application cannot be started on host '%s'\nbecause this host cannot be reached from host '%s':\n\n %s"));
3686 DtMsgLogMessage (smGD.programName, DtMsgLogError,
3687 message, hostName, localHost, program);
3693 netfile = tt_host_file_netfile (hostName, cwd);
3694 if (tt_pointer_error (netfile) != TT_OK) {
3696 message = strdup ((char *) GETMESSAGE (40, 14,
3697 "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]"));
3700 DtMsgLogMessage (smGD.programName, DtMsgLogError,
3701 message, program, hostName, cwd,
3702 tt_status_message (tt_pointer_error (
3710 * Add envp to the client's environ if the variable
3711 * is not in the ignoreEnvironment list
3713 if (useIgnoreEnvironmentResource && ignoreEnvPtr && envp)
3714 tmpEnv = RemoveEnvironmentVars (envp);
3716 if ((_DtSPCSpawn (program, netfile, execArray, tmpEnv, channel,
3717 hostName, NULL, cwd, errorMessage)) == SPC_ERROR) {
3718 DtMsgLogMessage (smGD.programName, DtMsgLogError, errorMessage);
3720 XtFree ((char *) tmpEnv);
3726 XtFree ((char *) tmpEnv);
3732 /*************************************<->*************************************
3739 * Fork and exec the default window manager
3752 *************************************<->***********************************/
3761 * These lines were added to support the builtin
3766 char *displayName,*dpy;
3768 hostName = SM_MALLOC(MAXPATHSM);
3769 displayName = SM_MALLOC(MAXPATHSM);
3771 if( gethostname(hostName, (sizeof(hostName) - 1) ) == 0)
3773 hostName[MAXPATHSM - 1] = '\0';
3774 dpy = getenv(DISPLAY_NAME);
3775 homeDir = getenv("HOME");
3778 strcpy(displayName, dpy);
3779 dpy = strchr(displayName, ':');
3784 sprintf(tmpExecWmFile, "%s/.dt/bin/%s/%s/dtwm", homeDir,
3785 hostName,displayName);
3786 if (access(tmpExecWmFile,X_OK) != 0)
3788 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3792 localWmLaunched = True;
3793 if (!smGD.userSetWaitWmTimeout)
3795 smRes.waitWmTimeout = 60000;
3801 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3806 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3810 SM_FREE(displayName);
3812 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
3813 * End of lines were added to support the builtin
3817 strcpy(tmpExecWmFile,CDE_INSTALLATION_TOP "/bin/dtwm");
3822 * Fork and exec the client process
3824 clientFork = vfork();
3827 * If the fork fails - Send out an error and return
3831 PrintErrnoError(DtError, smNLS.cantForkClientString);
3836 * Fork succeeded - now do the exec
3840 SetSIGPIPEToDefault ();
3844 * Set the gid of the process back from bin
3847 setregid(smGD.runningGID, smGD.runningGID);
3849 setgid(smGD.runningGID);
3850 setegid(smGD.runningGID);
3853 _DtEnvControl(DT_ENV_RESTORE_PRE_DT);
3855 #if defined(__osf__) || defined(CSRG_BASED)
3859 #endif /* __osf__ */
3861 MarkFileDescriptors (3, F_SETFD, 1);
3864 * These lines were added to support the builtin
3867 * execStatus = execlp(".../dt/bin/dtwm", "dtwm", (char *) 0);
3870 execStatus = execlp(tmpExecWmFile, "dtwm", (char *) 0);
3873 * ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^ ^^^^^
3874 * End of lines were added to support the builtin
3878 if(execStatus != 0 && (!localWmLaunched))
3880 PrintErrnoError(DtError, GETMESSAGE(16, 4, "Unable to exec process /usr/dt/bin/dtwm. No window manager will be started."));
3887 /*************************************<->*************************************
3894 * Fork a copy of ourselves and kill the parent off so that scripts starting
3895 * up the session manager can continue.
3907 *************************************<->***********************************/
3915 * Fork and exec the client process
3917 clientFork = fork();
3920 * If the fork fails - We have to exit so that the rest of the
3921 * script can continue
3925 PrintErrnoError(DtError, smNLS.cantForkClientString);
3930 * Fork succeeded - now kill the parent
3938 * Disassociate from parent
3940 #if defined(__osf__) || defined(CSRG_BASED)
3944 #endif /* __osf__ */
3949 /*************************************<->*************************************
3956 * This routine waits for the window manager to start. It uses a
3957 * resource (waitWmTimeout) with a dynamic default to determine how many
3958 * seconds to wait for WM start and then starts clients.
3963 * appContext = application context for the window
3964 * window = window id for the
3973 *************************************<->***********************************/
3978 XtIntervalId wmTimerId;
3980 XtAddEventHandler(smGD.topLevelWid,
3983 (XtEventHandler)HandleWMClientMessage,
3987 * Set a timer which stops the block on waiting for the
3988 * window manager to start
3991 wmTimerId = XtAppAddTimeOut(smGD.appCon,
3992 smRes.waitWmTimeout,
3993 WaitWMTimeout, NULL);
3995 while((smGD.dtwmRunning == False) && (wmTimeout == False))
3997 XtAppProcessEvent(smGD.appCon, XtIMAll);
4000 XtRemoveTimeOut(wmTimerId);
4001 XtRemoveEventHandler(smGD.topLevelWid,
4004 (XtEventHandler)HandleWMClientMessage,
4008 } /* END OF FUNCTION WaitForWM */
4011 /*************************************<->*************************************
4018 * Timeout procedure the WaitForCommand routine. It stops a loop waiting
4019 * for the window manager to get started.
4028 * wmTimeout = (global) flag that stops the loop
4033 *************************************<->***********************************/
4036 XtPointer client_data,
4041 } /* END OF FUNCTION WaitWMTimeout */
4045 /*************************************<->*************************************
4047 * HandleWMClientMessage
4052 * This is the event handler registered to recieve the client message
4053 * from dtwm when dtwm is ready for business
4056 *************************************<->***********************************/
4058 HandleWMClientMessage( Widget smWidget,
4062 if (event->type == ClientMessage)
4064 ProcessClientMessage(event);
4067 } /* END OF FUNCTION HandleWMClientMessage */
4072 /*************************************<->*************************************
4074 * FixEnvironmentData
4079 * If DISPLAY variable exists in the environment - remove it
4088 * wmTimeout = (global) flag that stops the loop
4093 *************************************<->***********************************/
4095 FixEnvironmentData( void )
4099 extern char **environ; /* MODIFIED - DISPLAY is remove if found. */
4101 for (i=0, ppchar = environ; *ppchar; ppchar++, i++)
4103 if ((strncmp (*ppchar, DISPLAY_NAME_EQUAL, strlen(DISPLAY_NAME_EQUAL))) == 0)
4106 * Change the DISPLAY environment variable.
4108 for (; *ppchar; ppchar++, i++)
4110 environ[i]=environ[i+1];
4119 /*************************************<->*************************************
4126 * After one screen is finished - set up the info for the next
4131 * cmdBuf - Buffer that holds all the invocation information
4132 * screen - Pointer to the screen number that we're currently working on
4133 * env - used to set up the environment for changing the display var
4134 * displayName - name of the current display
4138 * cmdBuf - old buffers are freed
4139 * screen - updated to point to the new screen info
4140 * done - tells whether the clients are done being exec'd
4141 * linec - *GLOBAL* sets line being read from
4147 *************************************<->***********************************/
4149 ResetScreenInfo(unsigned char **cmdBuf,
4151 unsigned int *cmdSize,
4156 SM_FREE((char *) cmdBuf[*screen]);
4158 while((cmdSize[*screen] == 0) && (*screen < smGD.numSavedScreens))
4163 if(*screen >= smGD.numSavedScreens)
4169 sprintf((char *)env,"%s%s%d", DISPLAY_NAME_EQUAL, displayName, *screen);
4173 parseP = cmdBuf[*screen];
4179 /*************************************<->*************************************
4181 * RemoteRequestFailed ()
4186 * If a request to the command invoker fails, this callback will be called.
4187 * It will then try to execute the command by performing a remsh on it.
4200 *************************************<->***********************************/
4202 RemoteRequestFailed(char *message,
4205 static char *cmdBuf = NULL;
4206 static char *tmpCmdBuf = NULL;
4207 char *errorString = NULL;
4210 static int cmdBufSize = 0;
4213 RemoteReq *tmpReq = (RemoteReq *) client_data;
4216 * If the memory for the buffer has not been malloced - do so
4220 cmdBuf = SM_MALLOC((200 * sizeof(char)) + 1 );
4223 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4226 cmdBufSize = 200 + 1;
4228 tmpCmdBuf = SM_MALLOC((200 * sizeof(char)) + 1 );
4229 if(tmpCmdBuf == NULL)
4231 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4236 * Copy in the host and command field and execute the command
4239 tmpSize = (strlen(REMOTE_CMD_STRING) +
4240 strlen((char *) tmpReq->hostPtr) +
4241 strlen((char *) tmpReq->cmdPtr) + 1);
4243 if(tmpSize >= cmdBufSize)
4245 cmdBuf = SM_REALLOC(cmdBuf, (tmpSize) * sizeof(char));
4249 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4253 cmdBufSize = tmpSize;
4255 if(tmpCmdBuf != NULL)
4257 tmpCmdBuf = SM_REALLOC(tmpCmdBuf, (tmpSize) * sizeof(char));
4258 if(tmpCmdBuf == NULL)
4260 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4265 sprintf(cmdBuf, REMOTE_CMD_STRING, tmpReq->hostPtr, tmpReq->cmdPtr);
4268 * save cmdBuf for error message, cmdBuf is changed
4269 * by CreateExecString
4271 if (tmpCmdBuf != NULL)
4273 strcpy(tmpCmdBuf,cmdBuf);
4276 CreateExecString(cmdBuf);
4277 if(smExecArray[0] != NULL)
4279 (void) StartClient(smExecArray[0], smExecArray, NULL, NULL,
4280 NULL, False, False, -1);
4282 if (tmpCmdBuf != NULL)
4284 tmpString = GETMESSAGE(16, 8,
4285 "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");
4288 (char *)SM_MALLOC((strlen(tmpString) +
4289 strlen((char *)tmpReq->hostPtr) +
4290 strlen((char *)tmpReq->cmdPtr) +
4291 strlen(tmpCmdBuf) + 1 ) *
4294 if(errorString == NULL)
4296 PrintErrnoError(DtError, smNLS.cantMallocErrorString);
4300 sprintf(errorString, tmpString, tmpReq->hostPtr,
4301 tmpReq->cmdPtr, tmpCmdBuf );
4302 PrintError(DtError, errorString);
4303 SM_FREE(errorString);
4308 * Now check to make sure that this isn't the last remote request.
4309 * If so, free the data
4313 if(numRemoteExecs == 0)
4315 for(i = 0;i < smGD.numSavedScreens;i++)
4317 if(actRemoteSize[i] > 0)
4319 SM_FREE((char *) remoteBuf[i]);
4329 /*************************************<->*************************************
4331 * RemoteRequestSucceeded ()
4336 * If a request to the command invoker succeeds, this callback will be called.
4337 * It decrements the remote execution counter, and frees the info if
4338 * remote executions are finished
4351 *************************************<->***********************************/
4353 RemoteRequestSucceeded(char *message,
4360 if(numRemoteExecs == 0)
4362 for(i = 0;i < smGD.numSavedScreens;i++)
4364 if(actRemoteSize[i] > 0)
4366 SM_FREE((char *) remoteBuf[i]);
4372 /**************************************************************************
4376 **************************************************************************/
4380 char * databaseName)
4383 XSMPClientDBRecPtr pXSMPRec;
4384 ProxyClientDBRecPtr pProxyRec;
4389 if ((inputDB = OpenInputClientDB (databaseName,
4391 &smXSMP.dbSessionId)) == NULL) {
4392 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogError, 1);
4396 if (!smXSMP.dbVersion) {
4397 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogWarning, 2);
4398 smXSMP.dbVersion = SM_VENDOR_NAME;
4401 if (!smXSMP.dbSessionId) {
4402 LogXSMPOpenDatabaseFailure (databaseName, DtMsgLogWarning, 3);
4403 smXSMP.dbSessionId = SM_RELEASE_NAME;
4407 * First start the XSMP clients
4411 if ((pXSMPRec = GetXSMPClientDBRec (inputDB)) == NULL)
4414 if (!CheckRequiredProperties (pXSMPRec, databaseName)) {
4415 FreeXSMPClientDBRec (pXSMPRec);
4419 if (StartXSMPClient (pXSMPRec, databaseName)) {
4421 XSMPClientDBRecPtr tmpRecPtr;
4423 pXSMPRec->next = NULL;
4425 if (!smXSMP.xsmpDbList) {
4426 smXSMP.xsmpDbList = pXSMPRec;
4431 * Find the end of the list
4433 for (tmpRecPtr = smXSMP.xsmpDbList;
4434 tmpRecPtr && tmpRecPtr->next != NULL;
4435 tmpRecPtr = tmpRecPtr->next);
4437 tmpRecPtr->next = pXSMPRec;
4440 FreeXSMPClientDBRec (pXSMPRec);
4444 * Now start the Proxy clients
4446 for (i = 0; ; i++) {
4448 if ((pProxyRec = GetProxyClientDBRec (inputDB)) == NULL)
4451 if (!CheckRequiredFields (pProxyRec, databaseName, i)) {
4452 FreeProxyClientDBRec (pProxyRec);
4456 (void) StartProxyClient (pProxyRec);
4458 FreeProxyClientDBRec (pProxyRec);
4461 (void) CloseClientDB (inputDB, False);
4469 XSMPClientDBRecPtr pDbRec,
4470 char * databaseName)
4472 return (StartClient (pDbRec->restartCommand[0],
4473 pDbRec->restartCommand,
4476 pDbRec->environment,
4479 pDbRec->screenNum));
4485 ProxyClientDBRecPtr pDbRec)
4487 return (StartClient (pDbRec->command[0],
4494 pDbRec->screenNum));
4499 ExecuteCommandProperty (
4501 ClientRecPtr pClientRec)
4504 char ** envp = NULL;
4506 PropertyRecPtr pPropRec;
4510 if ((pPropRec = GetPropertyRec (pClientRec, commandName)) == NULL)
4513 argv = (char **) XtMalloc ((pPropRec->prop.num_vals + 1) *
4518 for (i = 0; i < pPropRec->prop.num_vals; i++)
4519 argv[i] = pPropRec->prop.vals[i].value;
4520 argv[pPropRec->prop.num_vals] = NULL;
4522 cwd = GetArrayPropertyValue (pClientRec, SmCurrentDirectory);
4525 if ((pPropRec = GetPropertyRec (pClientRec, SmEnvironment)) != NULL) {
4526 envp = (char **) XtMalloc ((pPropRec->prop.num_vals + 1) *
4531 for (i = 0; i < pPropRec->prop.num_vals; i++)
4532 envp[i] = pPropRec->prop.vals[i].value;
4533 envp[pPropRec->prop.num_vals] = NULL;
4536 retValue = StartClient (argv[0], argv,
4537 pClientRec->clientHost,
4540 pClientRec->screenNum);
4542 XtFree ((char *) argv);
4544 XtFree ((char *) envp);
4550 /*************************************<->*************************************
4552 * ExecuteDiscardCommands -
4554 * Description: Executes all of the DiscardCommand properties in the
4555 * given client database
4559 *************************************<->***********************************/
4561 ExecuteDiscardCommands (
4565 XSMPClientDBRecPtr pXSMPRec;
4566 char * version = NULL;
4570 if ((inputDB = OpenInputClientDB (db, &version, &id )) == NULL) {
4571 str = strdup ((char *) GETMESSAGE (40, 26,
4572 "The following client database cannot be opened:\n\n %s\n\nThe 'DiscardCommand' properties cannot be run."));
4575 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str, db);
4581 XtFree ((char *) version);
4583 XtFree ((char *) id);
4586 if ((pXSMPRec = GetXSMPClientDBRec (inputDB)) == NULL)
4589 if (!pXSMPRec->discardCommand)
4592 if (!StartClient (pXSMPRec->discardCommand[0],
4593 pXSMPRec->discardCommand,
4594 pXSMPRec->clientHost,
4596 pXSMPRec->environment,
4599 pXSMPRec->screenNum)) {
4600 str = strdup ((char *) GETMESSAGE (40, 27,
4601 "An attempt to execute the 'DiscardCommand' property for\napplication '%s' failed."));
4604 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, str,
4609 FreeXSMPClientDBRec (pXSMPRec);
4612 (void) CloseClientDB (inputDB, False);
4617 CheckRequiredProperties (
4618 XSMPClientDBRecPtr pDbRec,
4619 char * databaseName)
4621 Boolean propsOK = True;
4623 if (!pDbRec->program) {
4624 LogMissingPropertyMessage (pDbRec, SmProgram,
4625 databaseName, DtMsgLogError);
4629 if (!pDbRec->restartCommand) {
4630 LogMissingPropertyMessage (pDbRec, SmRestartCommand,
4631 databaseName, DtMsgLogError);
4640 CheckRequiredFields (
4641 ProxyClientDBRecPtr pDbRec,
4642 char * databaseName,
4647 if (!pDbRec->command) {
4649 message = strdup ((char *) GETMESSAGE (40, 11,
4650 "The required resource '%s' is missing for client '%d'\nin the file '%s'."));
4655 DtMsgLogMessage (smGD.programName, DtMsgLogError, message,
4656 SmProgram, clientNum, databaseName);
4668 LogXSMPOpenDatabaseFailure (
4669 char * databaseName,
4670 DtMsgLogType msgType,
4673 char * message = NULL;
4678 case 1: data = databaseName;
4680 message = strdup ((char *) GETMESSAGE (40, msgNum,
4681 "The following session database could not be opened:\n\n '%s'"));
4684 case 2: data = versionStr;
4686 message = strdup ((char *) GETMESSAGE (40, msgNum,
4687 "The following session database does not contain\nthe required resource '%s':\n\n %s"));
4690 case 3: data = dtsessionIDStr;
4692 message = strdup ((char *) GETMESSAGE (40, msgNum,
4693 "The following session database does not contain\nthe required resource '%s':\n\n %s"));
4701 DtMsgLogMessage (smGD.programName, msgType, message, data);
4703 DtMsgLogMessage (smGD.programName, msgType, message,
4704 data, databaseName);
4711 LogMissingPropertyMessage (
4712 XSMPClientDBRecPtr pDbRec,
4714 char * databaseName,
4715 DtMsgLogType msgType)
4719 message = strdup ((char *) GETMESSAGE (40, 10,
4720 "The required property '%s' is missing for client\n\n %s\n\nin the file '%s'."));
4725 DtMsgLogMessage (smGD.programName, msgType, message,
4726 propName, pDbRec->clientId, databaseName);
4740 message = strdup ((char *) GETMESSAGE (40, 12,
4741 "The directory '%s'\nis not available for application '%s'.\n\nThe following directory will be used:\n\n %s"));
4746 DtMsgLogMessage (smGD.programName, DtMsgLogWarning, message,
4747 badDir, appName, goodDir);
4754 char ** RemoveEnvironmentVars (
4758 char ** retEnv = NULL;
4759 char **ppchar, **ppchar2;
4766 for (count = 0, ppchar = envp; ppchar && *ppchar; count++, ppchar++) ;
4768 retEnv = (char **) XtMalloc ((count + 1) * sizeof (char *));
4772 if (!ignoreEnvPtr) {
4773 for (count = 0, ppchar = envp; ppchar && *ppchar;
4774 count++, ppchar++) {
4775 retEnv[count] = *ppchar;
4777 retEnv[count] = NULL;
4782 for (count = 0, ppchar = envp; ppchar && *ppchar; ppchar++) {
4786 for (ppchar2 = ignoreEnvPtr; ppchar2 && *ppchar2; ppchar2++) {
4788 if ((!strncmp (*ppchar, *ppchar2, strlen (*ppchar2))) &&
4789 (((*ppchar)[strlen(*ppchar2)]) == '=')) {
4795 retEnv[count] = *ppchar;
4799 retEnv[count] = NULL;
4805 * MarkFileDescriptors - mark file descriptiors start_fd through open_max
4806 * with the given "cmd" and "data".
4808 * The code for calculating open_max was taken from DtSvc/DtUtil1/CmdMain.c
4811 MarkFileDescriptors (
4819 open_max = sysconf(_SC_OPEN_MAX);
4821 if (open_max == -1) {
4825 #if defined(USL) || defined(__uxp__) || defined(_AIX)
4826 open_max = FOPEN_MAX;
4828 open_max = FD_SETSIZE;
4830 #endif /* _SUN_OS */
4833 for (i = start_fd; i < open_max; i++)
4834 (void) fcntl (i, cmd, data);