Navigate another program
[Autolink] Menu
/* 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
[Back: Dummy program for the REXX Wrapper]
[Next: Using redirection for a simple process controller]