/****************************** Module Header ******************************* * * Module Name: cleandatb.cmd * * Clean WarpIN database entries for NEPMD. * * The WarpIN script handles both old and new package titles. It uses the old * titles, if they were already present in the database and otherwise the new * ones. This script renames the old package titles and removes additional, * old ones. * * This program is intended to be called only by code in MAIN.E at the * first EPM start after the NEPMD installation. This was changed from the * call by POSTWPI.EXE after WarpIN opened its database in share-deny mode * due to the xPrf functions. * * Copyright (c) Netlabs EPM Distribution Project 2008 * * $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' /* ----------------- 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 = '' GlobalVars = GlobalVars 'ErrorQueueName ErrorMessage' GlobalVars = GlobalVars 'RwIniLoaded Ini. App. Key. Pck.' /* -------------------------------------------- */ DO 1 ARG Parm . if Parm = 'NOMSG' THEN fErrMsg = FALSE else fErrMsg = TRUE Ini. = '' Ini._Handle.0 = 0 RwIniLoaded = '?' /* Get install dirs */ DO 1 UserDir = '' next = SysIni( 'USER', 'NEPMD', 'UserDir') IF next = 'ERROR:' THEN LEAVE UserDir = strip( next, 't', '00'x ) END DO 1 RootDir = '' next = SysIni( 'USER', 'NEPMD', 'RootDir') IF next = 'ERROR:' THEN LEAVE RootDir = STRIP( next, 't', '00'x ) END /* Get NEPMD.INI */ NepmdIni = '' IF UserDir <> '' THEN NepmdIni = STRIP( UserDir, 't', '\')'\bin\NEPMD.INI' ELSE DO IF RootDir <> '' THEN NepmdIni = STRIP( RootDir, 't', '\')'\myepm\bin\NEPMD.INI' END /* Query possible package ids, written by Initialize_GetTitle of nepmd.wis */ Pck. = '' Pck.0 = 0 IF NepmdIni <> '' THEN DO Pck._PrefixNames = STRIP( IniFunc( NepmdIni, 'Install', 'PckPrefixNames'), 'T', '00'x) IF Pck._PrefixNames = 'ERROR:' THEN Pck._PrefixNames = '' Pck.0 = STRIP( IniFunc( NepmdIni, 'Install', 'PckNames.0'), 'T', '00'x) IF Pck.0 = 'ERROR:' THEN Pck.0 = 0 DO p = 1 TO Pck.0 Pck._Names.p = STRIP( IniFunc( NepmdIni, 'Install', 'PckNames.'p), 'T', '00'x) END END /* Parse package prefix names */ n = 0 Pck._PrefixName.0 = 0 rest = Pck._PrefixNames /*SAY 'Pck._PrefixNames = 'Pck._PrefixNames*/ DO WHILE rest <> '' PARSE VAR rest next '|' rest IF next = '' THEN ITERATE n = n + 1 Pck._PrefixName.n = next /*SAY 'Pck._PrefixName.'n' = 'Pck._PrefixName.n*/ END Pck._PrefixName.0 = n Pck._NewPrefixName = Pck._PrefixName.1 Pck._OldPrefixName = Pck._PrefixName.n /* Parse package names */ DO p = 1 TO Pck.0 rest = Pck._Names.p n = 0 DO WHILE rest <> '' PARSE VAR rest next '|' rest IF next = '' THEN ITERATE n = n + 1 Pck._Name.p.n = next /*SAY 'Pck._Name.'p'.'n' = 'Pck._Name.p.n*/ END Pck.p.0 = n END /* Get BootDrive */ BootDrive = GetBootDrive() /* Find WarpIN database */ next = STRIP( IniFunc( 'USER', 'WarpIN', 'Path'), 'T', '00'x) IF next = 'ERROR:' THEN DO ErrorMessage = 'Error: WarpIN entry not found in user ini.' rc = ERROR.PATH_NOT_FOUND LEAVE END WarpInDir = next DataBase = WarpInDir'\DATBAS_'LEFT( BootDrive, 1)'.INI' /* Read database */ PckNumber. = '' PckNumberList = '' PckIndexList = '' App. = '' App.0 = 0 ExportLine. = '' ExportLine.0 = 0 next = IniFunc( DataBase, 'ALL:', 'App.') IF next = 'ERROR:' THEN DO ErrorMessage = 'Error: "'DataBase'" could not be read.' rc = ERROR.READ_FAULT LEAVE END /* Process database ini apps = package ids */ f = 0 FoundPck.0 = 0 DO i = 1 to App.0 /* Check prefix */ fPrefixFound = 0 DO n = 1 TO Pck._PrefixName.0 IF (POS( Pck._PrefixName.n, App.i) = 1) THEN DO fPrefixFound = 1 /*SAY 'FoundPck: App.i = 'App.i*/ LEAVE n END END IF \fPrefixFound THEN ITERATE /* Save found packagae */ f = FoundPck.0 + 1 FoundPck.f = App.i FoundPck.0 = f /* Parse package id */ PARSE VAR App.i FoundVendorName'\'FoundAppName'\'FoundPckName'\'FoundVersion FoundVersionStr.f = GetVersionStr( FoundVersion) /* Get new package name */ NewPckName = GetNewPckName( FoundPckName) NewPckName.f = NewPckName /* Build new package id */ NewPckId = Pck._NewPrefixName'\'NewPckName'\'FoundVersion NewPckId.f = NewPckId END /* Check if newer versions of a package are installed */ DO f = 1 TO FoundPck.0 fRemoveApp.f = 0 END DO f = 1 TO FoundPck.0 /*SAY 'f = 'f', NewPckName.f = 'NewPckName.f', FoundVersionStr.f = 'FoundVersionStr.f*/ IF fRemoveApp.f = 1 THEN ITERATE DO s = f + 1 TO FoundPck.0 IF NewPckName.f <> NewPckName.s THEN ITERATE IF FoundVersionStr.f >= FoundVersionStr.s THEN fRemoveApp.s = 1 ELSE fRemoveApp.f = 1 END END DO f = 1 TO FoundPck.0 IF fRemoveApp.f = 1 THEN ITERATE /* Query and process Requires key */ FoundRequiresVal = IniFunc( DataBase, FoundPck.f, 'Requires') IF FoundRequiresVal = 'ERROR:' THEN ITERATE rest = FoundRequiresVal Sep = '00'x NewRequiresVal = '' DO WHILE rest <> '' PARSE VAR rest NextId(Sep)rest /* Check prefix */ fRequiresPrefixFound = 0 DO n = 1 TO Pck._PrefixName.0 IF (POS( Pck._PrefixName.n, NextId) = 1) THEN DO fRequiresPrefixFound = 1 LEAVE n END END IF fRequiresPrefixFound THEN DO /* Parse package id */ PARSE VAR NextId FoundRequiresVendorName'\'FoundRequiresAppName'\'FoundRequiresPckName'\'FoundRequiresVersion /* Get new package name */ NewRequiresPckName = GetNewPckName( FoundRequiresPckName) /* Build new package id */ NewRequiresPckId = Pck._NewPrefixName'\'NewRequiresPckName'\'FoundRequiresVersion END ELSE NewRequiresPckId = NextId /* Build new Requires val */ NewRequiresVal = NewRequiresVal''NewRequiresPckId''Sep END /* Write new Requires val if different */ IF FoundRequiresVal <> NewRequiresVal THEN DO /*SAY 'rcx = IniFunc( 'DataBase', 'FoundPck.f', ''Requires'', 'TRANSLATE( NewRequiresVal, '.', '00'x)')'*/ rcx = IniFunc( DataBase, FoundPck.f, 'Requires', NewRequiresVal) IF rcx = 'ERROR:' THEN DO rc = ERROR.WRITE_FAULT EXIT( rc) END END END DO f = 1 TO FoundPck.0 /*SAY 'f = 'f', NewPckName.f = 'NewPckName.f', fRemoveApp.f = 'fRemoveApp.f', FoundVersionStr.f = 'FoundVersionStr.f*/ /* Remove old ini apps */ IF fRemoveApp.f = 1 THEN DO /*SAY 'rcx = IniFunc( 'DataBase', 'FoundPck.f', ''DELETE:'')'*/ rcx = IniFunc( DataBase, FoundPck.f, 'DELETE:') ITERATE END /* Rename database ini apps */ IF FoundPck.f <> NewPckId.f THEN DO /* Parse package id */ PARSE VAR FoundPck.f FoundVendorName'\'FoundAppName'\'FoundPckName'\'FoundVersion FoundVersionStr.f = GetVersionStr( FoundVersion) /*SAY 'rc = RenameIniApp( 'DataBase', 'FoundPck.f', 'NewPckId.f')'; rc = ERROR.NO_ERROR*/ rc = RenameIniApp( DataBase, FoundPck.f, NewPckId.f) IF rc <> ERROR.NO_ERROR THEN EXIT( rc) END END /* Close WarpIN database */ rcx = IniClose( DataBase) IF NepmdIni <> '' THEN DO /* Close NEPMD.INI */ rcx = IniClose( NepmdIni) END END /* Report error message */ IF ErrorMessage <> '' & fErrMsg THEN CALL SayErrorText EXIT( rc) /* ------------------------------------------------------------------------- */ GetNewPckName: PROCEDURE EXPOSE (GlobalVars) PARSE ARG FoundPckName NewPckName = '' DO p = 1 to Pck.0 DO n = 1 TO Pck.p.0 IF Pck._Name.p.n = FoundPckName THEN DO /* Use the first = newest name */ NewPckName = Pck._Name.p.1 LEAVE p END END END RETURN( NewPckName) /* ------------------------------------------------------------------------- */ GetVersionStr: PROCEDURE EXPOSE (GlobalVars) PARSE ARG Major'\'Minor'\'Revision'\'Fixlevel ThisVersionStr = Major'.'RIGHT( Minor, 4, '0')RIGHT( Revision, 4, '0')RIGHT( Fixlevel, 4, '0') RETURN( ThisVersionStr) /* ------------------------------------------------------------------------- */ /* RwIniLoaded is global */ LoadRwIni: PROCEDURE EXPOSE (GlobalVars) /* Must use a syntax signal handler to bypass a failing call of rwIniLoadFuncs */ SIGNAL ON SYNTAX NAME RwIniNotFound CALL RxFuncAdd 'rwIniLoadFuncs', 'RWINI', 'rwIniLoadFuncs' CALL rwIniLoadFuncs /* Restore the previous syntax signal handler */ SIGNAL OFF SYNTAX RwIniLoaded = 1 RETURN /* ------------------------------------------------------------------------- */ RwIniNotFound: /* RETURN here returns to where LoadRwIni was called */ RETURN /* ------------------------------------------------------------------------- */ IniClose: PROCEDURE EXPOSE (GlobalVars) PARSE ARG IniFile rcx = '' DO 1 IF RwIniLoaded <> 1 THEN LEAVE IF Ini._Handle.0 = 0 THEN LEAVE rcx = 'ERROR:' NumFound = 0 DO n = 1 TO Ini._Handle.0 IF TRANSLATE( IniFile) = TRANSLATE( Ini._File.n) THEN DO NumFound = n LEAVE END END IF NumFound = 0 THEN LEAVE n = NumFound IniHandle = Ini._Handle.n rcx = rwIniClose( IniHandle) IF n = Ini._Handle.0 THEN Ini._Handle.0 = Ini._Handle.0 - 1 Ini._Handle.n = '' Ini._File.n = '' END RETURN( rcx) /* ------------------------------------------------------------------------- */ /* If a stem name was specified as arg after ALL:, that stem var must be */ /* made global in the main program. */ IniFunc: PROCEDURE EXPOSE (GlobalVars) IniFile = '' IniApp = '' IniKey = '' IniVal = '' Sep = '00'x rcx = 'ERROR:' DO 1 /* Parse args */ NumArgs = ARG() SELECT WHEN NumArgs >= 4 THEN PARSE ARG IniFile, IniApp, IniKey, IniVal WHEN NumArgs >= 3 THEN PARSE ARG IniFile, IniApp, IniKey WHEN NumArgs >= 2 THEN PARSE ARG IniFile, IniApp OTHERWISE PARSE ARG IniFile END fWriteIni = 0 IF NumArgs >= 4 & ARG( 3) <> 'ALL:' THEN fWriteIni = 1 IF NumArgs = 3 & ARG( 3) = 'DELETE:' THEN fWriteIni = 1 /* Load rwIni */ IF RwIniLoaded = '?' THEN DO /*say 'RwIniLoaded = 'RwIniLoaded', CALL LoadRwIni'*/ RwIniLoaded = 0 CALL LoadRwIni END /*say 'RwIniLoaded = 'RwIniLoaded*/ /* rwIni: Find handle for IniFile */ IniHandle = '' fRwIniWriteFailed = 0 NumFound = 0 DO n = 1 TO Ini._Handle.0 IF TRANSLATE( IniFile) = TRANSLATE( Ini._File.n) THEN DO NumFound = n IniHandle = Ini._Handle.n fRwIniWriteFailed = (Ini._RwIniWriteFailed.n = 1) LEAVE END END /* Determine if rwIni can be used */ fUseSysIni = 0 SELECT WHEN RwIniLoaded <> 1 THEN fUseSysIni = 1 WHEN WORDPOS( TRANSLATE( IniFile), 'USER SYSTEM BOTH') > 0 THEN fUseSysIni = 1 WHEN IniFile = '' THEN /* Empty means BOTH */ fUseSysIni = 1 WHEN fWriteIni & fRwIniWriteFailed THEN fUseSysIni = 1 OTHERWISE NOP END IF \fUseSysIni THEN DO IF NumFound = 0 THEN DO 1 /* rwIni: Open IniFile first */ IniHandle = rwIniOpen( IniFile, 'N') IF IniHandle = 'ERROR:' THEN DO fUseSysIni = 1 LEAVE END n = Ini._Handle.0 n = n + 1 Ini._Handle.0 = n Ini._Handle.n = IniHandle Ini._File.n = IniFile NumFound = n END /* Call rwIni */ DO SELECT WHEN NumArgs >= 4 THEN rcx = rwIni( IniHandle, IniApp, IniKey, IniVal) WHEN NumArgs >= 3 THEN rcx = rwIni( IniHandle, IniApp, IniKey) WHEN NumArgs >= 2 THEN rcx = rwIni( IniHandle, IniApp) OTHERWISE rcx = rwIni( IniHandle) END /* If write failed, save that per ini and use SysIni */ IF fWriteIni & rcx = 'ERROR:' THEN DO n = NumFound Ini._RwIniWriteFailed.n = 1 fUseSysIni = 1 END END END IF fUseSysIni THEN DO /* Call SysIni */ SELECT WHEN NumArgs >= 4 THEN rcx = SysIni( IniFile, IniApp, IniKey, IniVal) WHEN NumArgs >= 3 THEN rcx = SysIni( IniFile, IniApp, IniKey) WHEN NumArgs >= 2 THEN rcx = SysIni( IniFile, IniApp) OTHERWISE rcx = SysIni( IniFile) END END END RETURN( rcx) /* ------------------------------------------------------------------------- */ RenameIniApp: PARSE ARG IniFile, App, NewApp rc = ERROR.NO_ERROR DO 1 IF App = NewApp THEN LEAVE Key. = '' Key.0 = 0 next = IniFunc( IniFile, App, 'ALL:', 'Key.') IF next = 'ERROR:' THEN DO ErrorMessage = 'Error: "'IniFile' -> 'App'" could not be read.' rc = ERROR.READ_FAULT LEAVE END Val. = '' DO k = 1 TO Key.0 Val.k = IniFunc( IniFile, App, Key.k) IF Val.k = 'ERROR:' THEN DO ErrorMessage = 'Error: "'IniFile' -> 'App' -> 'Key.k'" could not be read.' rc = ERROR.READ_FAULT LEAVE END END /*SAY App' -> 'NewApp': 'Key.0' keys found, rc = 'rc*/ IF rc <> ERROR.NO_ERROR THEN LEAVE DO k = 1 TO Key.0 /* Writing keys doesn't work with rwIni called by IniFunc */ next = IniFunc( IniFile, NewApp, Key.k, Val.k) IF next = 'ERROR:' THEN DO rc = ERROR.WRITE_FAULT LEAVE END END IF Key.0 = 0 THEN LEAVE next = IniFunc( IniFile, App, 'DELETE:') IF next = 'ERROR:' THEN rc = ERROR.WRITE_FAULT END RETURN rc /* ------------------------------------------------------------------------- */ GetBootDrive: PROCEDURE EXPOSE (GlobalVars) IF \RxFuncQuery( 'SysBootDrive') THEN BootDrive = SysBootDrive() ELSE PARSE UPPER VALUE VALUE( 'PATH',, env) WITH ':\OS2\SYSTEM' -1 BootDrive +2 RETURN( BootDrive) /* ----------------------------------------------------------------------- */ 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 */ WHEN ADDRESS() = 'EPM' THEN DO /*'sayerror' ErrorMessage*/ ThisFileName = SUBSTR( ThisFile, LASTPOS( '\', ThisFile) + 1) rcx = RxMessageBox( ErrorMessage, TRANSLATE( ThisFileName),, 'OK', 'ERROR') 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)