/****************************** Module Header ******************************* * * Module Name: epmshell.cmd * * Syntax: epmshell saveenv [] * epmshell loadenv * * This is used for saving and restoring the environment of a shell. The * parameter in the saveenv mode is used to minimize the size of * the saved . It makes contain only lines different from * . During restore, environment variables in the values are * expanded. * * This is done in REXX to be called from within a shell window. * * The previous mode to open an EPM shell is not used anymore. This is now * completely replaced by the following program object: * * EXENAME epm.exe * PARAMETERS 'shell' * STARTUPDIR (none) * * 'cdd "%*"' doesn't need to be appended to the 'shell' cmd anymore, because * XWorkplace's context menu feature for folders appends for objects in * the XWorkplace Configuration Folder tree. This dir is passed to the opened * shell window (by the 'shell' cmd) and the LoadDir proc executes 'cdd' * in that window. * * Copyright (c) Netlabs EPM Distribution Project 2006 * * $Id$ * * =========================================================================== * * This file is part of the Netlabs EPM Distribution package and is free * software. You can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software * Foundation, in version 2 as it comes in the "COPYING" file of the * Netlabs EPM Distribution. This library is distributed in the hope that it * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * ****************************************************************************/ /* Some header lines are used as help text */ HelpLine.Start = 5 HelpLine.End = 11 '@ECHO OFF' /* ----------------- Standard CMD initialization follows ----------------- */ SIGNAL ON HALT NAME Halt SIGNAL ON NOVALUE NAME RexxError SIGNAL ON SYNTAX NAME RexxError SIGNAL ON FAILURE NAME RexxError env = 'OS2ENVIRONMENT' TRUE = (1 = 1) FALSE = (0 = 1) CrLf = '0d0a'x Redirection = '>NUL 2>&1' PARSE SOURCE . . ThisFile GlobalVars = 'env TRUE FALSE CrLf Redirection ERROR. ThisFile' /* Some OS/2 Error codes */ ERROR.NO_ERROR = 0 ERROR.INVALID_FUNCTION = 1 ERROR.FILE_NOT_FOUND = 2 ERROR.PATH_NOT_FOUND = 3 ERROR.ACCESS_DENIED = 5 ERROR.NOT_ENOUGH_MEMORY = 8 ERROR.INVALID_FORMAT = 11 ERROR.INVALID_DATA = 13 ERROR.NO_MORE_FILES = 18 ERROR.WRITE_FAULT = 29 ERROR.READ_FAULT = 30 ERROR.SHARING_VIOLATION = 32 ERROR.GEN_FAILURE = 31 ERROR.INVALID_PARAMETER = 87 ERROR.ENVVAR_NOT_FOUND = 204 rc = ERROR.NO_ERROR CALL RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs' CALL SysLoadFuncs /* ----------------- Standard CMD initialization ends -------------------- */ /* Extend the environment, if not already */ lp = LASTPOS( '\', ThisFile) ThisDir = LEFT( ThisFile, lp - 1) next = VALUE( 'NEPMD_NAME',, env) IF next = '' THEN 'CALL' ThisDir'\..\..\netlabs\bin\EPMENV' /* ------------- Configuration ---------------- */ UserDir = VALUE( 'NEPMD_USERDIR',, env) Ini._Filename = UserDir'\bin\nepmd.ini' Ini._RegDefaults = 'RegDefaults' Ini._KeyPath = '\NEPMD\User\Shell\PromptValue' /* -------------------------------------------- */ GlobalVars = GlobalVars 'HelpLine. CmdStem. Ini.' DO 1 PARSE ARG Args Args = STRIP( Args) PARSE VAR Args SubCmd RestArgs SubCmd = STRIP( SubCmd) RestArgs = STRIP( RestArgs) SELECT /* Save environment */ WHEN TRANSLATE( SubCmd) = 'SAVEENV' THEN DO IF LEFT( RestArgs, 1) = '"' THEN PARSE VAR RestArgs '"'EnvFile'"' CompareFile ELSE PARSE VAR RestArgs EnvFile CompareFile EnvFile = STRIP( EnvFile) CompareFile = STRIP( CompareFile) IF LEFT( CompareFile, 1) = '"' THEN PARSE VAR CompareFile '"'CompareFile'"' /* Check arg */ IF EnvFile = '' THEN DO rc = ERROR.INVALID_PARAMETER LEAVE END rc = SaveEnv( EnvFile, CompareFile) END /* Load environment */ WHEN TRANSLATE( SubCmd) = 'LOADENV' THEN DO IF LEFT( RestArgs, 1) = '"' THEN PARSE VAR RestArgs '"'EnvFile'"' ELSE EnvFile = RestArgs /* Check arg */ IF EnvFile = '' THEN DO rc = ERROR.INVALID_PARAMETER LEAVE END rc = LoadEnv( EnvFile) END OTHERWISE /* Show help */ rc = ShowHelp() EXIT( ERROR.INVALID_PARAMETER) END END EXIT( rc) /* ----------------------------------------------------------------------- */ /* This gets the output of the SET cmd and compares each line with the */ /* contents of CompareFile. CompareFile was previously created by the E */ /* cmd ShellSaveEnv. Different lines are written to EnvFile. */ SaveEnv: PROCEDURE EXPOSE (GlobalVars) rc = ERROR.NO_ERROR DO 1 PARSE ARG EnvFile, CompareFile IF EnvFile = '' THEN DO rc = ERROR.INVALID_PARAMETER ShowError 'Error: EnvFile not specified.' EXIT( rc) END /* Write env of current shell to CmdStem. */ Cmd = 'set' rc = CmdOutputToStem( Cmd) /* Write env from CompareFile to CompareStem. */ CompareStem. = '' CompareStem.0 = 0 DO 1 IF CompareFile = '' THEN LEAVE next = STREAM( CompareFile, 'C', 'OPEN READ') IF next <> 'READY:' THEN LEAVE c = 0 DO WHILE (LINES( CompareFile) > 0) c = c + 1 CompareStem.c = LINEIN( CompareFile) END CompareStem.0 = c rcx = STREAM( CompareFile, 'C', 'CLOSE') END /* Save different lines of CmdStem. to EnvFile */ IgnoreStartStrings = 'WP_OBJHANDLE= WORKPLACE_' /* Query default SHELL prompt value for comparison */ DefaultPromptVal = STRIP( SysIni( Ini._Filename, Ini._RegDefaults, Ini._KeyPath),, 'T', '00'x) /* Delete EnvFile */ IF FileExist( EnvFile) THEN CALL SysFileDelete EnvFile DO e = 1 TO CmdStem.0 /* Ignore lines that start with StartString */ DO w = 1 TO WORDS( IgnoreStartStrings) StartString = WORD( IgnoreStartStrings, w) IF LEFT( CmdStem.e, LENGTH( StartString)) = StartString THEN ITERATE e END /* Compare with each line of CompareStem */ fFound = 0 DO c = 1 TO CompareStem.0 IF CompareStem.c = CmdStem.e THEN DO fFound = 1 LEAVE END END IF fFound THEN ITERATE /* Avoid lines that don't contain env vars, e.g. empty lines */ IF POS( '=', CmdStem.e) = 0 THEN ITERATE /* Check if val of PROMPT env var = default config val */ PARSE VALUE CmdStem.e WITH CmdVar'='CmdVal IF CmdVar = 'PROMPT' THEN IF CmdVal = DefaultPromptVal THEN ITERATE /* Not found, write to EnvFile */ CALL LINEOUT EnvFile, CmdStem.e END rcx = STREAM( EnvFile, 'C', 'CLOSE') END RETURN( rc) /* ----------------------------------------------------------------------- */ /* Reads an .env file and sets env vars or BeginLIBPATH or EndLIBPATH */ LoadEnv: PROCEDURE EXPOSE (GlobalVars) rc = ERROR.NO_ERROR PARSE ARG EnvFile IF EnvFile = '' THEN DO rc = ERROR.INVALID_PARAMETER ShowError 'Error: EnvFile not specified.' EXIT( rc) END /* Open file */ rcx = STREAM( EnvFile, 'C', 'OPEN READ') DO WHILE (LINES( EnvFile) > 0) /* Read line and skip comments */ ThisLine = LINEIN( EnvFile) IF (LEFT( ThisLine, 1) = ':') THEN ITERATE IF (STRIP( ThisLine) = '') THEN ITERATE IF (POS( '=', ThisLine) = 0) THEN ITERATE /* Get varname and value */ PARSE VAR ThisLine EnvVar'='EnvValue EnvVar = TRANSLATE( STRIP( EnvVar)) EnvValue = ExpandEnvVars( EnvValue) /* Set env var, handle *LIBPATH specially */ IF WORDPOS( EnvVar, 'BEGINLIBPATH ENDLIBPATH') THEN rcx = SetExtLibpath( EnvVar, EnvValue) /* Ignore COMSPEC env var here. It's already processed by the E cmd */ /* ShellLoadEnv. */ ELSE IF EnvVar = 'COMSPEC' THEN NOP ELSE rcx = VALUE( EnvVar, EnvValue, env) END /* Close file */ rcx = STREAM( EnvFile, 'C', 'CLOSE') RETURN( rc) /* ----------------------------------------------------------------------- */ /* StemVar must be global */ CmdOutputToStem: PROCEDURE EXPOSE (GlobalVars) rc = ERROR.NO_ERROR PARSE ARG Cmd, StemVar IF StemVar = '' THEN StemVar = 'CmdStem.' IF StemVar <> '' THEN DO IF RIGHT( StemVar, 1) <> '.' THEN StemVar = StemVar'.' CALL VALUE StemVar, '' CALL VALUE StemVar''0, 0 END QueueName = RXQUEUE( 'CREATE') PrevQueueName = RXQUEUE( 'SET', QueueName) Cmd '| RXQUEUE' QueueName cmdrc = rc DO WHILE QUEUED() <> 0 LineStr = LINEIN( 'QUEUE:') IF StemVar <> '' THEN DO l = VALUE( StemVar''0) + 1 CALL VALUE StemVar''0, l CALL VALUE StemVar''l, LineStr END END rc = RXQUEUE( 'DELETE', QueueName) CALL RXQUEUE 'SET', PrevQueueName rc = cmdrc RETURN( rc) /* ----------------------------------------------------------------------- */ SetExtLibpath: PROCEDURE EXPOSE (GlobalVars) PARSE ARG VarName, VarValue VarName = TRANSLATE( VarName) Type = LEFT( VarName, 1) IF Type = 'E' THEN VarName = 'ENDLIBPATH' ELSE DO Type = 'B' /* Default value */ VarName = 'BEGINLIBPATH' END rc = ERROR.NO_ERROR DO 1 /* Check for newer REXXUTIL.DLL */ fFunctionFound = 0 IF \RxFuncQuery( 'SYSQUERYEXTLIBPATH') THEN fFunctionFound = 1 /* Set extended LIBPATH. This persists even when SETLOCAL was used. */ IF fFunctionFound = 1 THEN rc = SysSetExtLIBPATH( VarValue, Type) ELSE 'SET 'VarName'='VarValue END RETURN( rc) /* ----------------------------------------------------------------------- */ /* Expands environment variables in a string. Keeps %...% string if env */ /* var isn't set. Returns the converted string. */ ExpandEnvVars: PROCEDURE EXPOSE (GlobalVars) String = ARG( 1) startp = 1 DO l = 1 TO LENGTH( String) /* just an upper limit, instead of FOREVER */ p1 = POS( '%', String, startp) IF p1 = 0 THEN LEAVE startp = p1 + 1 p2 = POS( '%', String, startp) IF p2 = 0 THEN LEAVE LeftPart = SUBSTR( String, 1, p1 - 1) EnvVarName = SUBSTR( String, p1 + 1, p2 - p1 - 1) RightPart = SUBSTR( String, p2 + 1) EnvVarValue = VALUE( EnvVarName,, env) /* Handle unset vars: keep %... or %...% string */ IF EnvVarValue = '' THEN ITERATE /* Value exists, replace %...% string and move startp */ startp = LENGTH( LeftPart) + LENGTH( EnvVarValue) + 1 String = LeftPart''EnvVarValue''RightPart END RETURN String /* ----------------------------------------------------------------------- */ FileExist: PROCEDURE EXPOSE (GlobalVars) rc = ERROR.NO_ERROR PARSE ARG FileName RETURN( STREAM( Filename, 'C', 'QUERY EXISTS') > '') /* ----------------------------------------------------------------------- */ DirExist: PROCEDURE EXPOSE (GlobalVars) rc = ERROR.NO_ERROR PARSE ARG Dirname Found.0 = 0 rcx = SysFileTree( Dirname, 'Found.', 'DO'); RETURN( Found.0 > 0) /* ----------------------------------------------------------------------- */ ShowHelp: PROCEDURE EXPOSE (GlobalVars) rc = ERROR.NO_ERROR /* Show help text */ DO i = 1 TO HelpLine.End ThisLineStr = LINEIN( ThisFile) IF i >= HelpLine.Start THEN SAY SUBSTR( ThisLineStr, 3) END /* Close file */ rcx = STREAM( Thisfile, 'C', 'CLOSE') RETURN( '') /* ----------------------------------------------------------------------- */ RunningInPm: PROCEDURE EXPOSE (GlobalVars) rc = ERROR.NO_ERROR next = SysTextScreenSize() RETURN( next == '0 0') /* ----------------------------------------------------------------------- */ /* Show info message in a message box and/or write to STDOUT */ ShowInfo: PROCEDURE EXPOSE (GlobalVars) rc = ERROR.NO_ERROR PARSE ARG Message IF RunningInPm() THEN DO /* Additionally write info message for easier copying from a */ /* command line window. */ CALL LINEOUT 'STDOUT', Message /* Show message box in PM mode */ Title = FILESPEC( 'N', ThisFile) /* Message length seems to be limited */ rcx = RxMessageBox( Message, Title, 'OK', 'INFORMATION') END ELSE CALL LINEOUT 'STDOUT', Message RETURN( '') /* ----------------------------------------------------------------------- */ /* Show error message in a message box and/or write to STDERR */ ShowError: PROCEDURE EXPOSE (GlobalVars) rc = ERROR.NO_ERROR PARSE ARG Message IF RunningInPm() THEN DO /* Additionally write info message for easier copying from a */ /* command line window. */ CALL LINEOUT 'STDERR', Message /* Show message box in PM mode */ Title = FILESPEC( 'N', ThisFile) /* Message length seems to be limited */ rcx = RxMessageBox( Message, Title, 'CANCEL', 'ERROR') END ELSE DO CALL LINEOUT 'STDERR', Message END RETURN( '') /* ----------------------------------------------------------------------- */ Halt: CALL ShowError 'Interrupted by user.' EXIT( 99) /* ----------------------------------------------------------------------- */ /* Give a standard REXX error message. */ /* This is for REXX error conditions only. */ /* System error codes and REXX error codes are different. */ RexxError: /* SIGL must be saved to not get overwritten later. */ ErrorLine = SIGL /* As an extension to the standard REXX error messages, */ /* the error condition will be appended to the error text. */ ConditionText = 'Condition: 'CONDITION( 'C') ConditionDescription = CONDITION( 'D') IF ConditionDescription <> '' THEN ConditionText = ConditionText', Reason: 'ConditionDescription ErrText = '' IF SYMBOL( 'rc') = 'VAR' THEN DO IF rc > 0 & rc < 100 THEN ErrText = ERRORTEXT( rc) END IF ErrText = '' THEN ErrText = ConditionText ELSE ErrText = ErrText', 'ConditionText /* Ensure that rc is set and that rc <> 0 is returned */ IF SYMBOL( 'rc') = 'VAR' THEN DO IF \( rc > 0 & rc < 100) THEN rc = 999 END ELSE rc = 999 ErrorMessage = '' IF ErrorLine > 0 THEN ErrorMessage = RIGHT( ErrorLine, 6)' +++ 'SOURCELINE( ErrorLine) IF ErrorMessage <> '' THEN ErrorMessage = ErrorMessage''CrLf ErrorMessage = ErrorMessage ||, 'REX'RIGHT( rc, 4, 0)': Error 'rc' running 'ThisFile', line 'ErrorLine': 'ErrText CALL ShowError ErrorMessage EXIT( rc)