/****************************** Module Header ******************************* * * Module Name: epmsp.cmd * * Syntax: epmsp * * Activate single-processor mode for the EPM executable. That is required * only for EPM.EXE, which is usually located in \OS2\APPS, when running on * a SMP system. It is not required for the EPM loader in \OS2. * * The command file can be run from both an EPM shell or an OS/2 cmd window. * It checks first, if processing is required. It returns standard OS/2 error * codes. * * EXECMODE.EXE is used. That is a system utility included since Warp 3. * Unfortunately it always returns rc = 0. Therfore its output has to be * parsed. * * If running in an EPM shell or if an EPM window is still open, the EPM * executable is unlocked. After successful processing from an EPM window, * that window is automatically restarted. (Usually this cmd is executed by * the WarpIN installation.) * * In order to give a suitable rc and to avoid unnecessary unlocking, several * checks are made and execmode is called up to three times. * * rc = 0 File was modified successfully * rc = 18 File doesn't need modification * Any other OS/2 error code: Error, file not processed. * * Copyright (c) Netlabs EPM Distribution Project 2020 * * $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. * ****************************************************************************/ IF ADDRESS() <> 'EPM' THEN '@ECHO OFF' CALL SETLOCAL /* ----------------- 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 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 -------------------- */ /* ------------- Configuration ---------------- */ ErrorQueueName = VALUE( 'NEPMD_RXQUEUE',, env) ErrorMessage = '' TypeOption = '-sp' /* Option for execmode: -sp (single-processor) or -mp (multiprocessor) */ GlobalVars = GlobalVars 'ErrorQueueName ErrorMessage' GlobalVars = GlobalVars 'LineStr. fOptions fMod fList fSingle' GlobalVars = GlobalVars 'FileListed. FileMod. FileUnMod. ' /* -------------------------------------------- */ DO 1 /* Init */ QueueName = '' PrevQueueName = '' /* 1) Check parameter. Give a standard OS/2 error code. */ EpmExe = VALUE( 'NEPMD_EPMEXECUTABLE',, env) IF EpmExe <> '' THEN DO IF \FileExist( EpmExe) THEN DO rc = ERROR.FILE_NOT_FOUND ErrorMessage = ErrorMessage'Error: EPM executable 'EpmExe' doesn''t exist, rc = 'rc'.'CrLf LEAVE END END ELSE DO EpmPath = VALUE( 'EPMPATH',, env) IF EpmPath = '' THEN DO rc = ERROR.ENVVAR_NOT_FOUND ErrorMessage = ErrorMessage'Error: EPMPATH is not specified, rc = 'rc'.'CrLf LEAVE END rest = EpmPath DO WHILE rest <> '' PARSE VAR rest next';'rest /* If epm.exe is found in EPMPATH, check if epm.ex is in the same dir */ IF FileExist( next'\epm.exe') THEN DO IF FileExist( next'\epm.ex') THEN DO EpmExe = next'\epm.exe' LEAVE END END END IF EpmExe = '' THEN DO rc = ERROR.FILE_NOT_FOUND ErrorMessage = ErrorMessage'Error: EPM executable wasn''t found in EPMPATH, rc = 'rc'.'CrLf LEAVE END END /* 2) Test EpmExe: Check if already processed */ /* Search execmode.exe */ next = SysSearchPath( 'PATH', 'execmode.exe') IF next = '' THEN DO rc = ERROR.FILE_NOT_FOUND ErrorMessage = ErrorMessage'Error: execmode.exe wasn''t found in PATH, rc = 'rc'.'CrLf LEAVE END /* Create and set queue */ QueueName = RXQUEUE( 'CREATE') PrevQueueName = RXQUEUE( 'SET', QueueName) /* execmode -l checks the running executable rather than the file on disk. */ /* -sp is the default option */ Cmd = 'execmode -l 'TypeOption EpmExe /* Execute Cmd, fill queue and read queue into LineStr. array */ SAY 'Executing: 'Cmd Cmd '| RXQUEUE' QueueName LineStr.0 = 0 DO l = 1 TO QUEUED() PARSE PULL LineStr.l LineStr.0 = l END /* Parse output lines */ rcx = ParseLineStrArray() IF TRANSLATE( FileListed.1) = TRANSLATE( EpmExe) THEN DO rc = ERROR.NO_ERROR SELECT WHEN TRANSLATE( TypeOption) = '-SP' THEN DO TypeWord = 'single-processor' rc = ERROR.NO_MORE_FILES END WHEN TRANSLATE( TypeOption) = '-MP' THEN DO TypeWord = 'multiprocessor' rc = ERROR.NO_MORE_FILES END OTHERWISE TypeWord = 'unknown' TypeOption rc = ERROR.INVALID_PARAMETER END SAY EpmExe' runs already in 'TypeWord' mode.' LEAVE END IF rc <> ERROR.NO_ERROR & rc <> ERROR.NO_MORE_FILES THEN DO ErrorMessage = ErrorMessage'Error on testing 'EpmExe', rc = 'rc'.'CrLf LEAVE END /* 3) Process EpmExe */ /* -sp is the default option */ Cmd = 'execmode 'TypeOption EpmExe /* Execute Cmd, fill queue and read queue into LineStr. array */ SAY 'Executing: 'Cmd Cmd '| RXQUEUE' QueueName LineStr.0 = 0 DO l = 1 TO QUEUED() PARSE PULL LineStr.l LineStr.0 = l END /* Parse output lines */ rcx = ParseLineStrArray() IF rcx <> ERROR.NO_ERROR THEN DO IF rcx <> ERROR.SHARING_VIOLATION THEN DO /* ErrorMessage was already set by ParseLineStrArray */ rc = rcx LEAVE END ELSE DO /* 3) rcx = 32, unlock and process EpmExe again */ /* Clear ErrorMessage */ ErrorMessage = '' /* Search unlock.exe */ next = '' next1 = SysSearchPath( 'PATH', 'unlock.exe') IF next1 <> '' THEN next = next1 ELSE DO next2 = SysSearchPath( 'EPMTOOLSPATH', 'unlock.exe') IF next2 <> '' THEN next = next2 END IF next = '' THEN DO rc = ERROR.FILE_NOT_FOUND ErrorMessage = ErrorMessage'Error: unlock.exe wasn''t found in PATH, rc = 'rc'.'CrLf LEAVE END ELSE UnlockExe = next /* Unlock EpmExe */ Cmd2 = UnlockExe EpmExe SAY 'Executing: 'Cmd2 Cmd2''Redirection /* Try to process EpmExe again */ /* Execute Cmd, fill queue and read queue into LineStr. array */ SAY 'Executing: 'Cmd Cmd '| RXQUEUE' QueueName LineStr.0 = 0 DO l = 1 TO QUEUED() PARSE PULL LineStr.l LineStr.0 = l END /* Parse output lines */ rcx = ParseLineStrArray() IF rcx <> ERROR.NO_ERROR THEN DO /* ErrorMessage was already set by ParseLineStrArray */ rc = rcx LEAVE END END END IF TRANSLATE( FileMod.1) = TRANSLATE( EpmExe) THEN DO /* Successfully processed */ rc = ERROR.NO_ERROR /* If running in EPM, restart this window */ Cmd = 'pstat' SAY 'Executing: 'Cmd Cmd '| RXQUEUE' QueueName fEpmRunning = 0 DO l = 1 TO QUEUED() PULL LineStr IF POS( '\EPM.EXE', LineStr) > 0 THEN DO fEpmRunning = 1 LEAVE END END IF VALUE( 'NEPMD_NAME',, env) <> '' & fEpmRunning THEN DO SAY 'Restart...' "START epm /r 'ReStart closeother'" END LEAVE END END /* Cleanup */ if QueueName <> '' THEN rcx = RXQUEUE( 'DELETE', QueueName) if PrevQueueName <> '' THEN CALL RXQUEUE 'SET', PrevQueueName /* Report error message */ IF ErrorMessage <> '' THEN CALL SayErrorText CALL ENDLOCAL EXIT( rc) /* ------------------------------------------------------------------------- */ /* Parse LineStr. array */ ParseLineStrArray: PROCEDURE EXPOSE (GlobalVars) rc = ERROR.NO_ERROR fOptions = 0 fMod = 0 fList = 0 fSingle = 0 FileListed. = '' FileListed.0 = 0 FileMod. = '' FileMod.0 = 0 FileUnMod. = '' FileUnMod.0 = 0 DO l = 1 TO LineStr.0 StrippedLineStr = STRIP( LineStr.l) SELECT WHEN StrippedLineStr = '' THEN DO fOptions = 0 fMod = 0 fList = 0 fSingle = 0 END WHEN StrippedLineStr = 'ACTIVATED OPTIONS:' THEN fOptions = 1 WHEN StrippedLineStr = 'FILES MODIFIED:' THEN fMod = 1 WHEN StrippedLineStr = 'FILES LIST:' THEN fList = 1 WHEN WORD( StrippedLineStr, 1) = 'ERROR' THEN DO PARSE VAR StrippedLineStr . '(RC = 'rc')' LEAVE END WHEN fOptions = 1 THEN DO IF WORD( StrippedLineStr, 1) = 'SINGLE-PROCESSOR' &, (FileListed.0 > 0 | FileMod.0 > 0) THEN fSingle = 1 END WHEN fMod = 1 THEN DO PARSE VAR StrippedLineStr next' ('Comment')' IF Comment = 'modified' THEN DO f = FileMod.0 + 1 FileMod.f = next FileMod.0 = f END ELSE DO f = FileUnMod.0 + 1 FileUnMod.0 = f FileUnMod.f = next END END WHEN fList = 1 THEN DO f = FileListed.0 + 1 FileListed.f = StrippedLineStr FileListed.0 = f END OTHERWISE NOP END END RETURN( rc) /* ------------------------------------------------------------------------- */ FileExist: PROCEDURE PARSE ARG FileName RETURN( STREAM( Filename, 'C', 'QUERY EXISTS') > '') /* ----------------------------------------------------------------------- */ SayErrorText: PROCEDURE EXPOSE (GlobalVars) SELECT WHEN (ErrorMessage = '') THEN NOP /* Called by frame program: insert error */ /* message into private queue */ WHEN (ErrorQueueName <> '') THEN DO rcx = RXQUEUE( 'SET', ErrorQueueName) PUSH ErrorMessage END /* Called directly */ OTHERWISE DO SAY ErrorMessage 'PAUSE' END END RETURN( '') /* ----------------------------------------------------------------------- */ Halt: ErrorMessage = 'Interrupted by user.' CALL SayErrorText 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 SayErrorText EXIT( rc)