You can use REXX also to create a "Wrapper" for other (textmode) programs to filter the input and output for/from that program:
/* */ /* REXX "wrapper" program to call another program, queue the input */ /* for that program and filter the output of the program. */ /* */ /* In this example we call a program called "DBLOGIN.EXE" to logon */ /* to a database and extract some data. The program reads the UserId, */ /* the Password and the name of the database from STDIN. */ /* It writes all input (including the password!) also to STDOUT. */ /* To suppress the report of the Password on the screen we filter the */ /* output of the program before printing it to the screen. */ /* */ /* Use DBLOGIN.CMD to test this program. */ /* */ /* Note that the method used in this program is only possible for */ /* textmode programs using only STDIN, STDOUT and STDERR for input */ /* and output! */ /* */ /* (see also Navigate another program) */ /* */ /* */ /* History: */ /* 23.03.1996 /bs */ /* - initial release */ /* */ /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de */ /* */ /* turn off CTRL-BREAK */ signal OFF halt /* init some global variables */ /* name of the program to call */ /* Note: We are using the .CMD for test purposes */ /* only! */ exeToCall = "DBLOGIN.CMD" /* name of the default database */ defDatabase = "TestDB" /* default user ID */ defUserID = "TestUser" /* parameter to distinguish between the calls */ Pass2Marker = "$$SECOND$$" Pass3Marker = "$$THIRD$$" Pass4Marker = "$$FOURTH$$" EndOfProgram = "$$END$$" /* get the parameter of this program */ parse upper arg thisPass . /* check in which pass we are running */ select when ThisPass = pass4Marker then do /* fourth pass - read the output from the program */ /* filter it and write it to STDOUT */ /* ---------------------------------------------- */ /* STDIN in this pass is STDOUT from Pass 3 */ /* STDOUT in this pass is the screen */ /* ---------------------------------------------- */ call ExecutePass4 end /* when */ when ThisPass = pass3Marker then do /* third pass - call the program and write the */ /* end marker to STDOUT after */ /* the program stops */ /* ---------------------------------------------- */ /* STDIN in this pass is STDOUT from Pass 2 */ /* STDOUT in this pass is STDIN for Pass 4 */ /* ---------------------------------------------- */ parse arg . pass3Parms call ExecutePass3 pass3Parms end /* when */ when ThisPass = pass2Marker then do /* second pass - read the input for the program */ /* from the REXX queue and write it */ /* to STDOUT */ /* ---------------------------------------------- */ /* STDIN in this pass is the keyboard (not used, */ /* this pass reads the input from the REXX queue) */ /* STDOUT in this pass is STDIN for Pass 3 */ /* ---------------------------------------------- */ call ExecutePass2 end /* when */ otherwise do /* first pass - get the user input and call the */ /* EXE with redirected STDIN, STDOUT */ /* and STDERR. */ /* get the parameter for the program to call */ parse arg ParameterForEXE /* ---------------------------------------------- */ /* STDIN in this pass is the keyboard */ /* STDOUT in this pass is the screen */ /* ---------------------------------------------- */ call ExecutePass1 end /* otherwise */ end /* select */ exit /* error handler for CTRl-BREAK */ UserAbort: call LineOut , "Program aborted by the user!" exit 1 /* ------------------------------------------------------------------ */ /* function: execute pass 1 */ /* */ /* call: ExecutePass1 */ /* */ /* where: - */ /* */ /* returns: - */ /* */ ExecutePass1: /* first pass - get the user input and call the */ /* EXE with redirected STDIN, STDOUT */ /* and STDERR. */ /* turn on CTRL-BREAK in pass 1 */ signal ON halt name UserAbort /* show the logo */ call LineOut call LineOut , "*** DBLOGIN - Get Data from our database ***" call LineOut /* flush the queue */ do while queued() <> 0 parse pull end /* do while queued() <> 0 */ /* check the ANSI status */ /* We need ANSI support to suppress the printing */ /* of the password to the screen! */ curAnsiStatus = CheckAnsi() if curAnsiStatus <> 1 then do /* turn ANSI support on */ "@ANSI ON 2>NUL | rxqueue 2>NUL" /* check if the command was successful */ if CheckAnsi() <> 1 then do call LineOut , "Error: Cannot turn ANSI support on!" exit 254 end /* if CheckAnsi() <> 1 then */ end /* if curAnsiStatus <> 1 then */ /* get the name and path of this file */ parse source . . prog.__Name thisDir = fileSpec( "D", prog.__Name ) || , fileSpec( "P", prog.__Name ) /* search the program to call */ /* The program to call has to be in the current */ /* directory or in the directory where this */ /* wrapper program resides. */ select when stream( ".\" || exeToCall, "c", "QUERY EXISTS" ) <> "" then exeToCall = ".\" || exeToCall when stream( thisDir || exeToCall, "c", "QUERY EXISTS" ) <> "" then exeToCall = thisDir || exeToCall otherwise do call LineOut , "Error: Cannot find " || exeToCall || "!" exit 255 end /* otherwise */ end /* select */ call LineOut , " Using the program " exeToCall call LineOut /* get the data from the user */ call CharOut , " Please enter the UserID (def.: " || , defUserID || "): " myUserID = lineIn() if myUserID = "" then myUserID = defUserID myPassWord = GetPassword( " Please enter the Password: " ) call CharOut , " Please enter the database (def.: " || , defDataBase || "): " myDataBase = lineIn() if myDataBase = "" then myDataBase = defDataBase /* copy the user input to the queue */ queue MyUserID queue MyPassword queue MyDataBase call LineOut, " Now calling " || exeToCall || " ..." /* turn CTRL-BREAK off */ signal off HALT /* call the program */ "@cmd /c " prog.__Name pass2Marker "|" , prog.__Name pass3Marker exeToCall ParameterForEXE "2>>&1 |" , prog.__Name pass4Marker /* restore the ANSI status if neccessary */ if curAnsiStatus <> 1 then "@ANSI OFF 2>NUL | rxqueue 2>NUL" RETURN /* ------------------------------------------------------------------ */ /* function: execute pass 2 */ /* */ /* call: ExecutePass2 */ /* */ /* where: - */ /* */ /* returns: - */ /* */ ExecutePass2: PROCEDURE /* second pass - read the input for the program */ /* from the REXX queue and write it */ /* to STDOUT */ do while queued() <> 0 parse pull nextLine call LineOut, nextLine end /* do while queued() <> 0 */ RETURN /* ------------------------------------------------------------------ */ /* function: execute pass 3 */ /* */ /* call: ExecutePass3 parameters */ /* */ /* where: parameters - command to execute (prog and parms) */ /* */ /* returns: "RC = nn" where nn is the return code of the program */ /* or "nn" where nn is an error no. in case of an error */ /* */ ExecutePass3: PROCEDURE expose EndOfProgram /* third pass - call the program and write the */ /* end marker to STDOUT after */ /* the program stops */ /* init the return code */ rc = 0 /* install local error handlers */ signal on syntax name pass3End signal on error name pass3End signal on halt name pass3End signal on notready name pass3End parse arg pass3Parms /* call the program */ /* the use of "cmd /c" _IS_ necessary to avoid */ /* endless loops if the user presses CTRL-BREAK */ /* while running the program! */ "@cmd /c " || pass3Parms rc = "RC = " || rc pass3End: /* write the end of program marker */ /* This marker is necessary for Pass 4 to detect */ /* that the program has ended! */ call LineOut , EndOfProgram RETURN rc /* ------------------------------------------------------------------ */ /* function: execute pass 4 */ /* */ /* call: ExecutePass4 */ /* */ /* where: - */ /* */ /* returns: - */ /* */ ExecutePass4: PROCEDURE expose endOfProgram /* fourth pass - read the output from the program */ /* filter it and write it to STDOUT */ do forever call CharOut , " --> " /* get the next line from the output of the program */ thisLine = lineIn() testLine = translate( strip( thisLine ) ) /* check if the program has ended */ if testLine = endOfProgram then leave else do /* filter the output lines */ if pos( "PASSWORT", testLine ) | , pos( "PASSWORD", testLine ) <> 0 then call LineOut, "*** Password entered ***" else call LineOut, thisLine end /* else */ end /* do forever */ RETURN /* ------------------------------------------------------------------ */ /* function: get a password from the user (without showing it on the */ /* screen) */ /* */ /* call: GetPassword( {prompt} ) */ /* */ /* where: prompt - prompt string */ /* def.: none */ /* */ /* returns: the entered password */ /* */ /* note: This code only works with ANSI enabled */ /* */ /* */ GetPassword: PROCEDURE parse arg prompt /* show the prompt (if any) and set the screen */ /* attributes to notvisible */ call CharOut , prompt || "1B"x || "[8m" /* get the user input */ parse pull password /* reset the screen attributes */ call CharOut , "1B"x || "[0m" RETURN password /* ------------------------------------------------------------------ */ /* function: Check if ANSI is activated */ /* */ /* call: CheckAnsi */ /* */ /* where: - */ /* */ /* returns: 1 - ANSI support detected */ /* 0 - no ANSI support available */ /* -1 - error detecting ansi */ /* */ /* note: Tested with the German and the US version of OS/2 3.0 */ /* */ /* */ CheckAnsi: PROCEDURE thisRC = -1 trace off /* install a local error handler */ SIGNAL ON ERROR Name InitAnsiEnd "@ANSI 2>NUL | rxqueue 2>NUL" thisRC = 0 do while queued() <> 0 queueLine = lineIN( "QUEUE:" ) if pos( " on.", queueLine ) <> 0 | , /* USA */ pos( " (ON).", queueLine ) <> 0 then /* GER */ thisRC = 1 end /* do while queued() <> 0 */ InitAnsiEnd: RETURN thisRC