![[Toc]](../../toc.gif)
![[Index]](/idx.gif)
General input line enhancer
Some command line programs do not have a comfortable command line editor
(for example the Oracle CLI programs svgrmgr or sqlplus are programs of
this kind [at least the Solaris versions are])
For these programs you can use the REXX program below to add a command
line editor. Just call them via
myshell.cmd program_name {/lf|/cr} {parameter_for_the_program}
Using myshell.cmd you can also add some macro features or something like
this to such programs.
To create myshell.cmd do the following:
1. Copy this section into a file (e.g., TEXT.TMP)
2. Append CMDLINE.CMD to the end of the just created file
3. remove all lines until the first comment line from the file TEXT.TMP
4. rename the file TEXT.TMP to myshell.cmd
see also REXX Wrapper for textmode programs, Navigate another program,
Output & Input control, Using the handles 3 to 9 in REXX programs, Using
"Named Pipes"
/* ------------------------------------------------------------------ */
/* MYSHELL.CMD */
/* */
/* function: add command line editing to other programs */
/* */
/* usage: myshell.cmd {/lf|/cr} prog_to_execute {parameter} */
/* */
/* parameters: /lf */
/* use linefeed (0x0A) only (optional) */
/* /cr */
/* use carriage return (0x0D) only (optional) */
/* */
/* Default without /lf and /cr is CR/LF (0x0D0A) */
/* */
/* prog_to_execute */
/* fully qualified path and name of the program to */
/* execute */
/* */
/* parameter */
/* parameter for the program */
/* */
/* history: 14.07.2003 first release */
/* */
/* */
/* notes: This program only works if the called program reads */
/* the input from STDIN (standard input)! */
/* */
/* To test, if a program reads from STDIN create a plain */
/* textfile with commands for that program (e.g. in.txt) */
/* and then issue */
/* */
/* your_program <in.txt */
/* */
/* If this works, the program reads from STDIN and should */
/* work with MYSHELL.CMD */
/* */
/* MYSHELL.CMD ends if it finds one of the commands */
/* */
/* quit */
/* or */
/* exit. */
/* */
/* You may add further necessary commands to end */
/* MYSHELL.CMD (depending on the called program) to the */
/* variable */
/* */
/* exit_commands */
/* */
/* While MYSHELL.CMD is running you can enter REXX code */
/* using the prefix !, e.g. */
/* */
/* !say (4*55)/8 */
/* */
/* Commands starting with ! are interpreted by */
/* MYSHELL.CMD and NOT by the program to execute. */
/* To pipe a command starting with ! to the program to */
/* execute use " !" or "!!". */
/* */
/* Use !> to use the output of a REXX statement as */
/* input of your program, e.g. */
/* */
/* !>(4+55)/8 */
/* */
/* would write 7.375 to the STDIN of the program. */
/* */
/* One of the parameter /LF or /CR is neccessary if the */
/* program called does not handle the default line */
/* separator (CR/LF) correct. */
/* */
/* usage examples: */
/* */
/* myshell c:\os2\cmd.exe */
/* */
/* You can't use telnet with myshell.cmd - use tnpipe */
/* instead: */
/* */
/* myshell /LF c:\mtpn\bin\tnpipe.exe 127.0.0.1 */
/* */
/* Please note that MYSHELL.CMD does NOT work with */
/* every program, for example ftp.exe. */
/* But at least the cmd.exe works :-) */
/* */
/* (c) 2003 Bernd Schemmer, Germany, EMail: Bernd.Schemmer@gmx.de */
/* ------------------------------------------------------------------ */
/* commands to end MYSHELL.CMD */
/* add further exit commands here (depending */
/* of the programs you want to use MYSHELL with) */
exit_commands = "QUIT EXIT"
parse arg thisOption thisArgs
/* check for the options for MYSHELL.CMD */
select
when translate( thisOption ) = '/H' then
do
call lineOut, "Usage: myshell.cmd {/lf|/cr} prog_to_execute {parameter}"
exit 1
end /* when */
when translate( thisOption ) = '/LF' then
LINE_SEPARATOR = '0A'x
when translate( thisOption ) = '/CR' then
LINE_SEPARATOR = '0D'x
otherwise
LINE_SEPARATOR = '0A0D'x
thisOption = ''
parse arg thisArgs
end /* select */
/* get the name and path of this program */
parse source . . thisprog
thisProgname = filespec( "N", thisProg )
/* check if we're called as filter */
FILTER_MARKER = "$$FILTER$$"
if thisArgs = FILTER_MARKER then
do
/* run in filter mode */
do forever
if lines() = 0 then
exit
thisLine = lineIn()
call CharOut , thisLine || LINE_SEPARATOR
if Exitcommand( thisLine ) <> 0 then
exit
end /* do forever */
exit
end /* if */
if thisArgs <> "" then
do
/* check the supplied program name */
/* you may use SearchFilefile here to search a */
/* program in the PATH */
extProg = word( thisArgs, 1 )
if stream( extProg, 'c', 'QUERY EXISTS' ) = '' then
do
call lineOut "STDERR", thisProg || " - Error: can not find " || extProg || "!"
exit 255
end /* if */
else
do
/* */
/* The additional call of MYSHELL.CMD as filter */
/* between MYSHELL.CMD and the program to execute */
/* is necessary because it's not possible to use */
/* REXX commands to write to the handle 3. */
/* Therefor we need to use ECHO for this purpose. */
/* But ECHO always appends a CR/LF to the string */
/* - and some programs don't handle CR/LF in */
/* STDIN correct. */
/* */
/* It is possible to use the handle 2 (STDERR) */
/* instead of 3 to pipe the output of MYSHELL */
/* into the STDIN of the program to execute - but */
/* in this case all error messages of MYSHELL.CMD */
/* would also go to STDIN of the program to */
/* execute. */
"cmd /c " thisprog "3>>&1 1>>SCREEN$ | " thisProg thisOption FILTER_MARKER " | " thisArgs
end /* else */
end /* if */
else
do
/* second call, now the handle 3 (&3) is STDIN of */
/* the MYSHELL.CMD running in filter mode and */
/* STDOUT of MYSHELL.CMD running in filter mode */
/* is STDIN of the called program */
/* */
/* It's simple - isn't it? :-) */
/* */
call LineOut , ""
call LineOut , "---------------------------------------------------"
call LineOut , thisProgname || " is active "
call LineOut , "Use !rexx_command to execute a REXX command."
call LineOut , "Use !exit to leave after the other program ended."
call LineOut , "Just hit enter if you lost the prompt of the program. "
call LineOut , "---------------------------------------------------"
call LineOut , ""
do forever
inputLine = cmdLine()
if left( inputLine, 1 ) = '!' then
do
select
when left( inputLine, 2 ) = '!!' then
do
inputLine = substr( inputLine, 2 )
end /* if */
when left( inputline, 2 ) = '!>' then
do
call lineOut, " +++ REXX code found, now executing it +++"
if InterpretCommand( "inputLine=" substr( inputLine, 3 ) ) <> 0 then
iterate
end /* if */
otherwise
do
call lineOut, " +++ REXX code found, now executing it +++"
call InterpretCommand substr( inputLine, 2 )
call lineOut, " +++ executing of REXX code done. Press return to get your prompt back+++"
iterate
end /* else */
end /* select */
end /* if */
/* pipe the line to MYSHELL.CMD which then pipes */
/* it to STDIN of the program to execute */
"@echo." || inputline || ">&3"
if Exitcommand( inputLine ) <> 0 then
do
call LineOut , "---------------------------------------------------"
call LineOut , thisProgname || " ended."
call LineOut , "---------------------------------------------------"
leave
end /* if */
end /* do forever */
end /* else */
exit
/* ------------------------------------------------------------------ */
/* function: check for a command to exit */
/* */
/* call: exitCommand( inputLine ) */
/* */
/* where: inputLine - line to check */
/* */
/* returns: 1 - exit command not found */
/* else - exit command found */
/* */
/* */
/* note: This check is necessary if MYSHELL.CMD runs as filter */
/* and if MYSHELL.CMD runs in interactive mode to read the */
/* commands. Therefor this is a function. */
/* */
Exitcommand: PROCEDURE expose exit_commands
return wordpos( translate( arg( 1 ) ), exit_commands )
/* ------------------------------------------------------------------ */
/* function: interpret a command simulating "CALL ON SYNTAX" */
/* */
/* call: interpretCommand cmd */
/* */
/* where: cmd - command to interpret */
/* */
/* returns: 0 - execution okay */
/* else error executing the command */
/* */
/* */
/* note: do not use the keyword PROCEDURE! */
/* */
InterpretCommand:
parse arg IC.__CurLine
/* init return code with failure code */
IC.__ThisRC = 1
/* install a local error handler */
SIGNAL ON SYNTAX NAME InterpretCommand1
SIGNAL OFF NOVALUE
SIGNAL OFF FAILURE
SIGNAL OFF ERROR
SIGNAL OFF NOTREADY
/* execute the line */
interpret IC.__CurLine
/* set return code to OK */
/* this statement is not executed if an error */
/* occurs while executing the previous */
/* interpret command */
IC.__ThisRC = 0
InterpretCommand1:
if IC.__ThisRC = 1 then
do
IC.__ThisRC = rc
call LineOut , "---------------------------------------------------"
call LineOut , thisProgName || ": Error executing the REXX statement "
call LineOut , IC.__CurLine
call LineOut , "Condition(C) is " || condition('C')
call LineOut , "Condition(D) is " || condition('D')
call LineOut , "---------------------------------------------------"
end /* if */
/* drop unnecessary local variables */
drop IC.__CurLine
RETURN IC.__ThisRC
/* !!! insert CMDLINE.CMD here !!! */
Created using Inf-PHP v.2 (c) 2003 Yuri Prokushev
Created using Inf-HTML v.0.9b (c) 1995 Peter Childs