/* Migration script for Symantec Antivirus */ /* Created 22 May 03 by Chris Clayton */ /* Free for all to use, either in its entirety or portions, */ /* but will appreciate credit */ /* User modifiable definitions: */ /* create WPS folders, but could substitute another such an */ /* OD enhanced folder */ clFolderClass = 'WpFolder' /* ''TSEnhFolder' */ /* log file - change to '' if not needed */ fLogFile = 'SymaMigr.log' /* How to commit config.sys changes */ /* 'Y' = save changes to config.sys (old as config.mig) */ /* 'N' = save changes to config.mig (config.sys unchanged) */ sCommitCgs = 'N' /* INI file to change - Symantec uses os2.ini: 'USER' */ /* but changed it to 'symatest.ini' for testing */ fDestINI = 'symatest.ini' /* Symantec AntiVirus program and virus definition directories that are */ /* saved to the INI file- modify as required */ sSymantec = 'e:\symantec' sDefsDir = sSymantec||'\common\shared\virusdef' sVirusDir1 = sDefsDir||'\20001113.002' sVirusDir2 = sDefsDir||'\20001113.002' sVirusDir3 = sDefsDir||'\20030326.002' /* use the 'newest' here (look at DEFINFO.DAT) */ sVirusDir4 = sDefsDir||'\20001113.002' /* my icons directory */ sIcons = 'E:\UTILITY\ICONS\' /* find the OS/2 drive letter (system booted to) */ sBootDrive = Substr(Translate(Value('PATH',,'OS2ENVIRONMENT')),Pos('\OS2\SYSTEM',Translate(Value('PATH',,'OS2ENVIRONMENT')))-2,2) /* config.sys location - normally sBootdrive but use '.' for testing*/ sCfigDrive = '.' /* sBootDrive */ /* load all of the REXX utility functions, even though we only use a few */ Call RxFuncAdd 'SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs'; Call SysLoadFuncs; /* other global definitions */ /* variables that will contain config.sys additions to: */ sNewBook = '' /* BOOKSHELF environment variable */ sNewDpath = '' /* DPATH environment variable */ sNewHelp = '' /* HELP environment variable */ sNewLib = '' /* LIBPATH directive */ sNewPath = '' /* PATH environment variable */ /* the following stem variable is for additional config.sys entries */ stAddlCfg.0 = 0 /* the first will contain the number of entries */ /* .1 .. .n will contain the value of each entry */ bOK = 'FALSE' /* did the migration work? */ /* First create a destination folder on the Desktop */ /* Enter a unique object id and a folder name. Or you can specify an */ /* existing folder. You just need to know its object id. Unimaint has a */ /* a WPS tool that will display the properties of WPS objects. In this case */ /* the following code segment may be deleted and the variable sUtility must */ /* be set to the object id of the desired folder */ sFolder = '' sName = 'My Folder' rc = Message( 'Creating destination folder: '||sName ) rc = SysSetObjectData(sFolder,'' ) /* see if the objects exists */ if RC = 1 THEN DO rc = Message( ' Unable to create folder '||sName||' because object ID '||sFolder||' exists' ) EXIT END ELSE DO sOptions = 'OBJECTID='||sFolder||';CONCURRENTVIEW=NO;' sOptions = sOptions||'VIEWBUTTON=MINIMIZE;MINWIN=HIDE;' sOptions = sOptions||'ICONVIEW=NONGRID,NORMAL;ICONVIEWPOS=25,10,50,70' rc = SysCreateObject( clFolderClass, sName, '', sOptions, 'fail' ) IF RC = 0 THEN DO rc = Message( ' Unable to create folder '||sName ) rc = Message( ' Make sure it is deleted and retry the command.' ) EXIT END END /* sObject else */ /* Now create subfolders */ sApplicat = CreateFolder( sFolder, 'Application', '' ) sUtility = CreateFolder( sFolder, 'Utility', '' ) /* Migrate Symantec Antivirus if it exists */ fFile = 'E:\SYMANTEC\NAVOS2.EXE' rc = stream( fFile, 'c', 'query exist' ) if rc = fFile then DO sName = 'Symantec Antivirus' /* create a new folder in the sUtility folder */ sFolder = CreateFolder( sUtility, sName, '' ) IF sFolder = sUtility THEN /* folder creation didn't work */ rc = Message( ' So not migrating '||sName||' applications' ) ELSE /* could create the desired folder so add program objects */ DO /* Symantec Antivirus program */ /* This is a WPS program that does not need any additional object */ /* properties. So just supply a destination folder (sFolder), an */ /* object title (sName), an unique object id () and */ /* the program type: PM for WPS program. The extra parameters */ /* is passed as a null string '' */ rc = CreateApp( sFolder, sName, fFile, '', 'PM', '' ) /* Installation Utility */ /* Here we are using a program that is started in a command shell, */ /* Notice that the entire path to cmd.exe is specified. This is */ /* because CreateApp checks to see if the program exists before it */ /* will create an object. So it needs to know where the program is */ /* Here the program type is WINDOWABLEVIO for a windowed OS/2 */ /* session. Finally, we need to specify the contents of the */ /* 'parameters' field so the extra object properties variable sParms */ /* is used. We also specify an icon using a ';' to separate object */ /* property items */ sParms = 'PARAMETERS=/c e:\Symantec\epfinsts.exe /c:e:\Symantec\navos2.icf /o:drive;' sParms = sParms||'ICONFILE=E:\SYMANTEC\EPFIICIS.ICO' rc = CreateApp( sFolder, 'Installation Utility', sBootDrive||'\OS2\CMD.EXE', '', 'WINDOWABLEVIO', sParms ) /* Live Update */ rc = CreateApp( sFolder, 'Live Update', 'E:\SYMANTEC\NAVLUOS2.EXE', '', 'PM', '' ) /* Scan a: object */ sParms = 'PARAMETERS=a:\*.* /doallfiles /repair /s+;ICONFILE='||sIcons||'VIRUS.ICO' rc = CreateApp( sFolder, 'Scan a:', 'E:\SYMANTEC\NAVDXOS2.EXE', '', 'WINDOWABLEVIO', sParms ) /* create Startup Norton Program Scheduler program object */ rc = CreateApp( sFolder, 'Startup Norton Program Scheduler', 'E:\SYMANTEC\OS2SCHED.EXE', '', 'PM', '' ) /* Now create Uninstall Norton Antivirus program object */ rc = CreateApp( sFolder, 'Uninstall Norton Antivirus', 'E:\SYMANTEC\VDEFINST.EXE', '', 'PM', 'PARAMETERS=/u' ) /* config.sys changes Symantec Antivirus doesn't actually need these */ /* entries. They are included as an example of how to change: */ /* a) the various path environment entries. The next function */ /* adds a path that is to be added to the LIBPATH= statement. */ /* The sNewLib variable is both passed and returned. This is */ /* because the path entries are accumulated together as additional */ /* applications are migrated later on (ConcactPath knows to separate */ /* entries using a ';') Since this function is used to process */ /* different path variables (see the list of definitions above), */ /* the string 'LIBPATH' is passed for logging purposes */ sNewLib = ConcactPath( sNewLib, 'E:\SYMANTEC', 'LIBPATH' ) sNewHelp = ConcactPath( sNewHelp, 'E:\SYMANTEC', 'HELP' ) sNewPath = ConcactPath( sNewPath, 'E:\SYMANTEC', 'PATH' ) /* b) AddEntry is used to save entire config.sys lines in a stem */ /* variable for addition to the end of the new config.sys file. */ /* Here we add a comment and an environment variable. We could */ /* also add anything else an application may need, */ /* such as device drivers */ rc = AddCfgEntry( 'REM Symantec Antivirus' ) rc = AddCfgEntry( 'SET SYMANTEC=E:\SYMANTEC' ) /* create INI file entries */ /* Adding entries to an INI files is easy, if you're not faint of heart */ /* You need to specify an INI file: 'USER' for os2.ini, 'SYSTEM' for */ /* os2sys.ini (most apps shouldn't mess with this one), or a file name */ /* Here we specified fDestINI. If the file does not exist, it will be */ /* created for you using the path specified in fDerstINI. Note, Symantec */ /* expects these entries to be in the OS/2 user file, os2.ini. In this */ /* example code, a file name is specified for testing purposes. When all */ /* is working then fDestINI is set to 'USER' */ /* The next variable in CreateINIentry is the application name, followed */ /* by the key name. The routine checks to see if this application and key */ /* combination exist in the specified INI file. If they do, the key value */ /* is read and returned by the function to rc unchanged. If they do not */ /* exist, the the application and key are added with the specified key */ /* value, here the contents of sDefsDir. REXX strings are not null */ /* terminated, so the the final variable specified whether a null is to */ /* add to the key value ('Y') or not ('N'). Upon return rc contains */ /* a null string '' is the key creation was successful or 'ERROR:' if */ /* it was not */ rc = CreateINIentry( fDestINI, 'SymantecInstalledApps', 'AVENGEDEFS', sDefsDir, 'Y' ) rc = CreateINIentry( fDestINI, 'SymantecNAV', 'AVDefsDir', sDefsDir, 'Y' ) rc = CreateINIentry( fDestINI, 'SymantecNAV', 'InstallDir', sSymantec, 'Y' ) rc = CreateINIentry( fDestINI, 'SymantecNAV', 'InstallVersion', '5.0', 'Y' ) rc = CreateINIentry( fDestINI, 'SymantecSharedDefs', 'NAVOS2_50_AP1', sVirusDir1, 'Y' ) rc = CreateINIentry( fDestINI, 'SymantecSharedDefs', 'NAVOS2_50_AP2', sVirusDir2, 'Y' ) rc = CreateINIentry( fDestINI, 'SymantecSharedDefs', 'NAVOS2_50_NAVOS2', sVirusDir3, 'Y' ) rc = CreateINIentry( fDestINI, 'SymantecSharedDefs', 'NAVOS2_50_QUAR', sVirusDir4, 'Y' ) /* looks like the migration worked, */ /* but then I didn't do a lot of checking of returns */ bOK = 'TRUE' END /* create folder else */ END /* Symantec AntiVirus folder */ /* if the migration worked then make changes to config.sys */ /* The sCommitCfs flag specifies whether to commit changes */ /* to config.sys or config.mig. See above */ IF bOK = 'TRUE' THEN rc = UpdateConfigSys( sCommitCgs ) EXIT bOK \= 'TRUE' /* The following are the functions that do the work of the migration process */ /* Being an old 'C' programmer, I always return something back to the */ /* calling program. Here the returns are nearly all indications of how */ /* successful the operation was. Any variables that are in these routines */ /* that are not parsed as arguments are global variable (used across the */ /* program) and care needs to be taken to be sure they are properly defined */ /* before the routine is called. Also a few, such as rc, are used internally */ /* and their contents may change. So caution is required when using these */ /* variable with the main body of the program */ /*--------------------------------------------------------------------------- rc = Message( sMessage ) types a message onto the console and outputs it to a log file (if defined) arguments sMessage Info to display. Note, use the concation operator (||) to include multiple strings and REXX variables returned rc the return code from LINOUT ( 0 = ok, anything else ?) global fLogFile set to the log file name or '' if not needed internal rc LINEOUT return code ---------------------------------------------------------------------------*/ Message: PARSE ARG sMessage SAY sMessage rc = 0 IF fLogFile \= '' THEN DO rc = LINEOUT( fLogFile, sMessage ) /* open file & write message */ rc = LINEOUT( fLogFile ) /* close file */ END /* fLogFile IF */ return rc /* end of Message */ /*--------------------------------------------------------------------------- sReturn = CreateApp( sDest, sName, fFile, sObject, sType, sExtras ) creates a program object named sName within folder sDest Note: This function automatically sets the Startup Directory value to the program path. If another directory is desired, you must use SysSetObjectData to make the correction: rc = SysSetObjectData( sDest, 'STARTUPDIR=path' ) arguments sDest Destination folder object id - must exist sName icon title fFile program file name with complete path sObject object id - must be unique sType program type such as (see WinCreateObject for more): PM - WPS program WINDOWABLEVIO - OS/2 windowed WINDOWEDVDM - DOS windowed sExtras additions to object creation options, such as parameters format is: option1=value1;option2=value2; ... values may contain blanks but must be terminated by ';' returned sReturn 1 if successful, 0 otherwise internal rc return code from function calls sDir program path sOptions object creation options sReturn return from SysCreateObject() or 0 ---------------------------------------------------------------------------*/ CreateApp: PARSE ARG sDest, sName, fFile, sObject, sType, sExtras sReturn = 0 rc = stream( fFile, 'c', 'query exist' ) if rc = fFile then DO rc = SysSetObjectData( sObject, '' ) /* see if the object exists */ if rc = 1 THEN rc = Message( ' Unable to create '||sName||' because object ID '||sObject||' exists' ) ELSE DO sDir = filespec( "drive", fFile )||filespec( "path", fFile) rc = Message( 'Creating '||sName||' object' ) sOptions = 'OBJECTID='||sObject||';STARTUPDIR='sDir';EXENAME='||fFile||';' sOptions = sOptions||'PROGTYPE='||sType||';CONCURRENTVIEW=NO;MINWIN=VIEWER' IF sExtras \= '' THEN sOptions = sOptions||';'||sExtras sReturn = SysCreateObject( 'WpProgram', sName, sDest, sOptions, 'replace' ) IF sReturn = 0 THEN rc = Message( ' Unable to create '||sName||' object' ) END /* sObject else */ END /* fFile if */ ELSE rc = Message( sName||' does not exist - program object not created' ) return sReturn /* end of CreateApp */ /*--------------------------------------------------------------------------- sReturn = CreateFolder( sDest, sName, sObject ) creates a folder named sName within folder sDest Note: this routine may replace a folders with the same name if one currently exists within the destination folder. The object id is checked to make sure it is not a duplicate of an existing one, but the name is not. THe WPS may be smart enough to take care of this duplicate name problem, but this has not been tested arguments sDest Destination folder object id - must exist sName folder name sObject object id for the desired folder - must be unique returned sReturn object id: if successful the created folder's otherwise the destination's global clFolderClass class of the folder type to be created internal rc return from function calls sObject folder object id sOptions folder creation options ---------------------------------------------------------------------------*/ CreateFolder: PARSE ARG sDest, sName, sObject sReturn = sDest rc = Message( ' Creating folder: '||sName ) rc = SysSetObjectData( sObject,'' ) /* see if the object exists */ if rc = 1 THEN rc = Message( ' Unable to create folder '||sName||' because object ID '||sObject||' exists' ) ELSE DO sOptions = 'OBJECTID='||sObject||';CONCURRENTVIEW=NO;VIEWBUTTON=MINIMIZE;' sOptions = sOptions||'MINWIN=HIDE;ICONVIEW=NONGRID,NORMAL' rc = SysCreateObject( clFolderClass, sName, sDest, sOptions, 'replace' ) IF rc = 0 THEN rc = Message( ' Unable to create folder '||sName ) ELSE sReturn = sObject END /* sObject else */ return sReturn /* end of CreateFolder */ /*--------------------------------------------------------------------------- sResult = MoveObject( sSource, sDest, sName ) A routine to move objects from one location to another arguments sSource Object ID to be moved sDest Object ID of location to move to sName Source object description (for log) returned sResult operation success: 1 = moved, 0 = didn't internal rc return code from Message sResult Object function return codes ---------------------------------------------------------------------------*/ MoveObject: PARSE ARG sSource, sDest, sName rc = Message( ' Moving object: '||sName ) sResult = SysSetObjectData( sSource, '' ) /* see if the object exists */ if sResult = 0 THEN rc = Message( " Not moved - doesn't exist!" ) ELSE DO sResult = SysMoveObject( sSource, sDest ) IF sResult = 0 THEN rc = Message( ' Not moved - check ids' ) END RETURN sResult /* end of MoveObject */ /*--------------------------------------------------------------------------- sResult = ShadowObject( sSource, sDest, sName ) A routine to create a shadow of an object arguments sSource Object ID to be shadowed sDest Object ID of the location of the new shadow sName Source object description (for log) returned sResult operation success: 1 = shadowed, 0 = didn't internal rc return code from Message sResult Object function return codes ---------------------------------------------------------------------------*/ ShadowObject: PARSE ARG sSource, sDest, sName rc = Message( ' Shadowing object: '||sName ) sResult = SysSetObjectData( sSource, '' ) /* see if the object exists */ if sResult = 0 THEN rc = Message( " Not shadowed - doesn't exist!" ) ELSE DO sResult = SysCreateShadow( sSource, sDest ) IF sResult = 0 THEN rc = Message( ' Not shadowed - check ids' ) END RETURN sResult /* end of ShadowObject */ /*--------------------------------------------------------------------------- sReturn = CreateINIentry( sINIfile, sApp, sKey, sVal, sNull ) tries to create an INI file entry for Application sAdd with keyword sKey and value sVal. If sKey exists, then the current value is returned and no changes are made. input: sINIfile INI file to modify: 'USER', 'SYSTEM', or a file name Note: if file name doesn't exist, it will be created sApp Application name used to store profile information sKey Keyword name holding profile information sVal Application keyword value sNull add a NULL terminator to key value? 'Y' = yes, 'N' = no returned sReturn return from SysIni internal rc return code from message sReturn return code from SysIni ---------------------------------------------------------------------------*/ CreateINIentry: PARSE ARG sINIfile, sApp, sKey, sVal, sNull rc = Message( ' checking for ini file entry "'sApp'"' ) sReturn = SysIni( sIniFile, sApp, sKey ) IF sReturn = 'ERROR:' THEN DO rc = Message( ' creating ini entry for key "'sKey'"' ) IF TRANSLATE( sNull ) = 'Y' THEN sVal = sVal||'0'x sReturn = SysIni( sIniFile, sApp, sKey, sVal ) IF sReturn = '' THEN rc = Message( ' successfully added "'sVal'"' ) ELSE rc = Message( ' not successful: SysIni return = "'sReturn'"' ) END ELSE rc = Message( ' entry exists: "'sReturn'"' ) return sReturn /* end of CreateINIentry */ /*--------------------------------------------------------------------------- sDest = Concactpath( sDest. sSource, sPlace ) A routine to concact a single directory path onto a variable that contains a string of paths to be added to a given config.sys environment variable arguments sDest the variable that contains the paths to be added sSource the path to add on sPlace the environment variable name to add to (such as PATH) this is used for logging puposes returned sDest the new path additions internal dPos position of ';' in sSource dLen length of sSource rc return code from function calls sCurDir current working directory sNewDir directory that DIRECTORY changes to ---------------------------------------------------------------------------*/ ConcactPath: PARSE ARG sDest, sSource, sPlace IF sSource \= '' THEN DO /* some to add on, so do it */ rc = Message( ' Adding "'||sSource||'" to '||sPlace ) sCurDir = DIRECTORY() /* check that sSource is a directory that exists */ sNewDir = DIRECTORY( sSource ) /* try to change to it */ IF TRANSLATE( sNewDir ) = TRANSLATE( sSource ) THEN /* could */ rc = DIRECTORY( sCurDir ) /* it exists, so change back */ ELSE /* doen't exist, so issue a warning & use anyway */ rc = Message( ' WARNING: '||sSource||' does not exist' ) sDest = sDest||sSource /* add on new path to existing string */ dPos = LASTPOS( ';', sSource ) /* check for a terminating ';' */ dLen = LENGTH( sSource ) IF dPos \= dLen THEN sDest = sDest||';' /* no ';' at end, so add */ END /* sSource if */ return sDest /* end of ConcactPath */ /*--------------------------------------------------------------------------- rc = AddCfgEntry( sEntry ) adds a single line to the stem list that contains entries to be added to config.sys arguments sEntry the string to be added returned stAddlCfg.0 the numbers of entries in the stem list internal i no. of entries ---------------------------------------------------------------------------*/ AddCfgEntry: PARSE ARG sEntry IF sEntry \= '' THEN DO /* something to add */ i = stAddlCfg.0 /* find out how many are already there */ i = i + 1 /* increment to the next slot */ stAddlCfg.i = sEntry /* save line in next slot */ stAddlCfg.0 = i /* update the no. of entries counter */ rc = Message( ' added config.sys line: "'||sEntry||'"' ) END /* sEntry if */ return stAddlCfg.0 /* end of AddCfgEntry */ /*--------------------------------------------------------------------------- rc = UpdateConfigSys( sReplace ) Updates config.sys sNew.... path variable additions and adds any entries in stAddlCfg Note: this routine is modified code from the IBM Works migration script (and now more readable and compact) arguments sReplace Y = change entries and save to sBootDrive\config.sys (original config.sys is saved as config.mig) N = save changes in sBootDrive\config.mig (original config.sys is unchanged) returned sReturn the return code from LINOUT ( 0 = ok, anything else ?) global sBootDrive current OS/2 system drive (or '.' if testing) sNewBook BOOKSHELF paths to add on sNewDpath DPATH paths to add on sNewPath PATH paths to add on sNewLib LIBPATH paths to add on stAddlCfg stem variable containing the lines to add to config.sys internal fCurConfig original config.sys file fNewConfig config file to be created tmpconfig a temporary file for copying purposes rc return from function calls sReturn return from LINOUT sInLine a config.sys line sOS2var the config.sys variable (part before '=') sOS2value corresponding value (after '"' ) ---------------------------------------------------------------------------*/ UpdateConfigSys: PARSE ARG sReplace fCurConfig = sCfigDrive||'\CONFIG.SYS' /* the current config.sys */ fNewConfig = sCfigDrive||'\CONFIG.MIG' /* the new one with changes */ tmpconfig = sCfigDrive||'\IWTMP.SYS' /* temp file (could use REXX routine) */ '@del 'fNewConfig ' 2>nul >nul' /* make sure that config.mig is deleted */ DO WHILE LINES( fCurConfig ) /* scan through the entire file */ sInLine = LINEIN( fCurConfig ) /* reading in one line at a time */ /* separate variable and value */ PARSE VALUE sInLine WITH sOS2var '=' sOS2value sOS2var = TRANSLATE( sOS2var ) /* make sure all uppercase */ SELECT WHEN sOS2var = 'SET BOOKSHELF' THEN /* add BOOKSHELF entries */ sReturn = UpdateConfLine( fNewConfig, sInLine, sNewBook ) WHEN sOS2var = 'SET DPATH' THEN /* add DPATH entries */ sReturn = UpdateConfLine( fNewConfig, sInLine, sNewDpath ) WHEN sOS2var = 'SET HELP' THEN /* add HELP entries */ sReturn = UpdateConfLine( fNewConfig, sInLine, sNewHelp ) WHEN sOS2var = 'SET PATH' THEN /* add PATH entries */ sReturn = UpdateConfLine( fNewConfig, sInLine, sNewPath ) WHEN sOS2var = 'LIBPATH' THEN /* add LIBPATH entries */ sReturn = UpdateConfLine( fNewConfig, sInLine, sNewLib ) /*--------------------------------------------------------------------------- Since you are already scanning through the config.sys file, this is a good opportunity to tailor existing lines at their current location, or add additional lines before or after them. Here are a few examples WHEN sOS2var = 'PROTSHELL' THEN DO /* add c-a-d PROTSHELL entry */ sReturn = lineout( fNewConfig, sInLine ) sReturn = lineout( fNewConfig, 'rem ** PROTSHELL=E:\CADCMDR\CADCMDR.EXE' ) END WHEN sOS2var = 'SWAPPATH' THEN /* change SWAPPATH entry */ sReturn = lineout( fNewConfig, 'SWAPPATH=E:\ 4096 98304' ) Notice the following example uses value portion of the line WHEN sOS2value = 'USBMSD.ADD' THEN /* fixup USB rem media entry */ sReturn = lineout( fNewConfig, 'BASEDEV=USBMSD.ADD /FLOPPIES:0 /REMOVABLES:1' ) end of examples ---------------------------------------------------------------------------*/ OTHERWISE /* write the exising line out to the new config file */ sReturn = lineout( fNewConfig, sInLine ) END /* select */ END /* LINES DO */ IF stAddlCfg.0 > 0 THEN DO /* add additional config entries */ DO i = 1 TO stAddlCfg.0 sReturn = LINEOUT( fNewConfig, stAddlCfg.i ) END /* i DO */ END /* stAddlCfg IF */ sReturn = LINEOUT( fNewConfig ) /* close the files */ sReturn = LINEOUT( fCurConfig ) /* replace the orig config.sys with the new one */ IF TRANSLATE( sReplace ) = 'Y' THEN DO '@erase 'tmpconfig' 2>nul >nul' /* make sure temp file is deleted */ '@rename 'fCurConfig' 'tmpconfig' >nul' /* rename current to temp */ '@rename 'fNewConfig' 'fCurConfig' >nul' /* rename new to config.sys */ '@rename 'tmpconfig' 'fNewConfig' 2>nul >nul' /* rename temp to new */ rc = Message( ' '||fCurConfig||' updated succesfully. Your old file has been renamed to '||fNewConfig ) END ELSE rc = Message( ' '||fNewConfig||' contains the changes. Your original '||fCurConfig||' is unchanged.' ) return sReturn /* end of UpdateConfigSys */ /*--------------------------------------------------------------------------- rc = UpdateConfLine( fOutFile, sInput, sAddition ) Add text to an existing line and write the result to the new config.sys arguments fOutFile output file name to write modified entry to sInput current value of line in config.sys sAddition string to add to sInput returned sReturn the return code from LINOUT ( 0 = ok, anything else ?) internal sLen length of a string sPos position of a substring in another string sReturn return code from LINEOUT ---------------------------------------------------------------------------*/ UpdateConfLine: PARSE ARG fOutFile, sInput, sAddition IF sAddition \= '' THEN DO /* something to add on, so do it */ /* the following line checks to see if the additional path is already in */ /* the existing path. This is nice, but only works if the entire string */ /* is duplicated. Really should check each path entry for duplication */ /* Not hard to do, but messy. Might implement in the future */ sPos = POS( TRANSLATE( sAddition ), TRANSLATE( sInput )) IF sPos = 0 THEN DO /* not there, so add on */ sPos = LASTPOS( ';', sInput ) /* check for a terminating ';' */ sLen = LENGTH( sInput ) IF sPos \= sLen THEN sInput = sInput||';' /* no ';' so add it */ sInput = sInput||sAddition /* add on changes */ END /* pos if */ END /* sAddition IF */ sReturn = LINEOUT( fOutFile, sInput ) /* write result to new config file */ return result /* end of UpdateConfLine */ /*--------------------------------------------------------------------------- sDest = ConcactTabID( sDest, iTab, sObjID, sPlace ) A routine to concact a Tab Launchbar object onto a variable that contains a string of Tab objects arguments sDest contains the tab object ids to be added iTab tab number to add to sObjID object id to add on sPlace folder/program name to add (for logging) returned sDest the new object id additions internal rc function return codes ---------------------------------------------------------------------------*/ ConcactTabID: PARSE ARG sDest, iTab, sObjID, sPlace IF sObjID \= '' THEN DO /* something to add on, so do it */ rc = Message( ' Adding "'||sPlace||'" to tab '||iTab ) rc = SysSetObjectData(sObjID,'' ) /* see if the object exists */ IF rc = 0 THEN /* doesn't, so ignore */ rc = Message( ' WARNING: '||sPlace||' does not exist, not added' ) ELSE /* does, so add onto desired tab string */ sDest = sDest||iTab||'='||sObjID||',' END /* sObjID if */ return sDest /* end of ConcactTabID */