/* sample code to navigate a program by monitoring its output and */ /* sending the necessary keystrokes to it. */ /* */ /* note: The program to navigate must use STDIN for its input and */ /* STDOUT and/or STDERR for its output. */ /* */ /* Some OS/2 commands write all or parts of their output to */ /* STDERR if STDOUT is redirected to a file or into a pipe! */ /* Some OS/2 commands do NOT write a CR/LF after a prompt for */ /* an input. This is for example true for the FORMAT program. */ /* To get around this, we always wait for the line preceding */ /* the prompts from the FORMAT program (see below). */ /* */ /* (see also REXX Wrapper for textmode programs) */ /* */ /* In this example we use "FORMAT A: /q" */ /* */ /* Save this code in a file with the name "TEST.CMD" and call it with */ /* TEST <RETURN> */ /* */ /* Tested with OS/2 WARP Version 3 (German) and OS/2 WARP BETA 2 */ /* Version 2.99 (English) */ /* */ /* */ /* (c) 1996 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de */ /* */ /* get the name of this program */ parse source . . prog.__Name /* output device for our messages (we cannot */ /* use STDOUT for the messages!!! */ prog.__outputDevice = "STDERR:" /* get the parameter to check if this is the */ /* first, second or third call */ parse arg prog.__Parameter . select /*************************** third process ****************************/ /* --- put the output of the format command into the queue (FIFO) --- */ when prog.__Parameter == "$$THIRD$$" then do thisLine = "" /* this process ends after writing the last */ /* output message of FORMAT into the queue */ /* message 1273 = "Eine weitere Diskette formatieren (J/N)?" GER */ /* "Format another diskette (Y/N)? USA */ lastFormatMsg = SysGetMessage( 1273 ) do until pos( lastFormatMsg, thisLine ) <> 0 if lines() <> 0 then do /* read the output of the FORMAT program ... */ thisLine = lineIN() /* ... and write it into the REXX queue */ queue thisLine end /* if lines() <> 0 then */ end /* do until pos( lastFormatMsg, ... */ /* put the end marker for process 2 into the */ /* queue */ queue "***END***" end /* when */ /*************************** second process ***************************/ /* --- monitor the output of the FORMAT command and write the --- */ /* necessary input for the FORMAT command to STDOUT */ when prog.__Parameter == "$$SECOND$$" then do /* init the variables with the messages */ /* indicating that FORMAT needs some input */ /* message 1507 = "Dateisystemtyp für den Datenträger ist: " GER */ /* "The type of file system for the disk is " USA */ firstAskForInput = substr( SysGetMessage( 1507 ), 1, 25 ) /* message 1288 = "Namen für den Datenträger (max. ... " GER */ /* "Enter up to 11 characters for the ..." USA */ secondAskForInput = substr( SysGetMessage( 1288 ), 1, 45 ) /* message 1306 = "%1 verfügbare Zuordnungseinheiten ... " GER */ /* "%1 available allocation units on disk." USA */ thirdAskForInput = substr( SysGetMessage( 1306 ), 3, 20 ) outputOK = 0 /* just for fun: Show an "in progress" message */ call charOut prog.__OutputDevice , "Formatting " do until OutputOK == 1 call charOut prog.__OutputDevice, "\" || "08"X || "/" || "08"x /* wait until output of the FORMAT command is */ /* available */ if queued() == 0 then iterate /* monitor the output from the FORMAT command */ curFormatLine = strip( lineIn( "QUEUE:" ) ) /* check if the FORMAT command ended */ if curFormatLine = "***END***" then OutputOk = 1 select when pos( FirstAskForInput, curFormatLine ) <> 0 then do /* FORMAT needs some input to begin the */ /* format -- so give it a CR/LF */ call lineOut , "" end /* when */ when pos( SecondAskForInput, curFormatLine ) <> 0 then do /* FORMAT needs some input for the volume */ /* label -- so give it the label */ call lineOut , "Test" end /* when */ when pos( thirdAskForInput, curFormatLine ) <> 0 then do /* FORMAT needs to know if it should format */ /* another diskette -- tell it that we won't */ /* format another diskette */ call lineOut, "N" end /* when */ otherwise do /* do nothing */ end /* otherwise */ end /* select */ end /* do until OutputOK == 1 */ /* end the in progress message */ call lineOut prog.__OutputDevice, "... done." end /* when */ /***************************** first call *****************************/ /* --- execute the FORMAT command --- */ otherwise do "@cls" call lineOut prog.__OutputDevice, "" call lineOut prog.__OutputDevice,, "Example for navigating a program " || , "by monitoring the output" call lineOut prog.__outputDevice,, "Here we call FORMAT A: /Q to show how it works." call lineOut prog.__OutputDevice, "" if queued() <> 0 then do /* flush the REXX queue */ do while queued() <> 0 tempLine = lineIn( "QUEUE:" ) end /* do while queued() <> 0 */ end /* if queued() <> 0 then */ /* load the necessary functions from the DLL */ /* REXXUTIL */ call LoadREXXUtil /* wait until theres a diskette in drive A: */ call InsertDiskDialog /* execute the FORMAT command with the input */ /* coming from a second copy of this program */ /* and the output written to a REXX queue by */ /* a third copy of this program */ "@cmd /c " prog.__Name "$$SECOND$$ | " || , /* second process */ " format A: /q | " || , /* FORMAT command */ prog.__Name "$$THIRD$$" /* third process */ end /* otherwise */ end /* select */ EXIT 0 /* ****************************************************************** */ /* sub routines */ /* ------------------------------------------------------------------ */ /* routine to wait until a diskette is in drive A: */ /* ------------------------------------------------------------------ */ InsertDiskDialog: PROCEDURE InsertDiskDialogAgain: /* install a local error handler to check if */ /* the drive A: is ready */ SIGNAL ON NOTREADY Name InsertDiskDialogAgain call lineOut , "Insert a disk to FORMAT into drive A: " || , "and press enter" tempLine = lineIn() call stream "A:\*" RETURN /* ------------------------------------------------------------------ */ /* routine to load the necessary functions from REXXUTIL */ /* ------------------------------------------------------------------ */ LoadREXXUtil: PROCEDURE call rxFuncAdd "SysGetMessage", "REXXUTIL", "SysGetMessage" /* install a local error handler to check if */ /* the DLL was loaded */ SIGNAL ON SYNTAX NAME LoadRexxUtilError t = SysGetMessage( 1 ) RETURN LoadREXXUtilError: call lineOut, "Error: Cannot load the DLL REXXUTIL!" EXIT 255