Command I/O Redirection [ COMMUNICATOR 3000/XL XL RELEASE 3.0 ] MPE/iX Communicators
COMMUNICATOR 3000/XL XL RELEASE 3.0
Command I/O Redirection
by Scott Cressler, Jeff Vance, and Rich Webber
Commercial Systems Division
The following information outlines the procedures for using the Command
I/O Redirection feature of the MPE XL CI.
USER INTERFACE
The Command I/O Redirection feature of the MPE XL CI is invoked by
entering a redirection specification, that is, a redirection indicator,
<, > or >>, followed by a file name or a backreference to a file
equation. Since redirection is supported for only a single file,
wild-carding on the file name is meaningless and will result in an error.
If < is used, the input to that command is read from the named file,
rather than from the terminal for sessions (or spooled STDIN for a job).
If > or >> is used, the output of that command is sent to the named file,
rather than to $STDLIST. The difference between > and >> will be
discussed later. Spaces are allowed between the redirection indicator
and the file name.
In the following example, a file containing editor commands is provided
as input to the editor. Also, all output from the editor is redirected
to $NULL. This includes the banner, prompt, and all command output.
:editor <edinput >$null
The next example illustrates how a system manager might produce a quick
list of the UDCs they currently have available. This might be used for
comparing to a previous list or for mailing to someone using HPDESK.
:showcatalog >udcnames
The final example shows the syntax that might be used to execute several
compiles. Assume that COMP is a command file that uses the INPUT command
to read from the terminal the name of a file that is to be compiled. It
performs the compile, sending the listing to $STDLIST, and then reads
another file name.
:file lp602;dev=epoc;env=lp602.hpenv.sys
:listfile o@,qualify >fils2cmp
:comp <fils2cmp >*lp602
The example first uses LISTFILE to produce a file, FILS2CMP, containing a
list of the files beginning with O in the logon group and account. Each
file name listed will be fully qualified. COMP is then executed with its
input redirected to the file FILS2CMP. COMP would read file names from
the file, one by one. Each file would be compiled and its listing sent
to the same spoolfile defined by the file equation for LP602.
Output redirection behaves differently depending on the output
redirection indicator used, > or >>. When opening a file for output
redirection using the >filename format, CIOR will attempt to open a new
TEMP file with the name specified. If the file named is an existing TEMP
file, the file is overwritten.
When the >>filename format of output redirection is used, CIOR will still
try to open a new TEMP file with the given name. However, if the file
already exists in the TEMP directory, it will be opened for APPEND
access. These two types of output redirection provide the user
flexibility in defining access to the output file depending upon the
application. If the goal of the user is to create a file containing only
the output of the current command, >filename should be used. If,
however, the output is a logging message, or the user is creating a file
with several commands, the >>filename form of output redirection should
be used.
When a file is opened by CIOR, whether for redirection of input or
output, certain defaults are used. Any of the defaults may be overridden
by using a backreference to a file equation rather than a filename. The
most interesting aspect of these defaults is that CIOR defaults to the
TEMP directory. This will minimize the chances of the user redirecting
output to a file she or he didn't want to overwrite. Since TEMP files
are deleted when the user logs off, their accidental deletion is usually
less critical. When output is redirected to a file which does not exist,
a new file will be created. It will be created with the following
defaults:
* 256 byte, variable length, ASCII records
* DISC = 10000
* TEMP file
* NOCCTL
When output is redirected using the >filename redirection specification
to a TEMP file that exists, the following defaults will apply to the
open:
* WRITE, SHARED Access, MULTI Access
If the >>filename redirection specification is used instead, APPEND
access is requested instead of WRITE. A default also exists for input
redirection. A file that input has been redirected to is opened by first
attempting to open a TEMP file with the name specified. Thismakes
default input redirection consistent with default output redirection. If
no such TEMP file exists, an attempt is made to open a permanent file
with that name.
When input is redirected, the file must exist and will be opened with the
following defaults:
* Look for TEMP file first, then old permanent.
* READ, SHARED access
The following example illustrates the concepts presented in the last few
paragraphs:
:echo text file1 >edinput
:echo find "patt1" >>edinput
:echo delete >>edinput
:echo keep >>edinput
:echo exit >> edinput
:listfile, disc; temp
TEMPORARY FILES FOR SCOTT.UI,SPOOLER
ACCOUNT= UI GROUP= SPOOLER
FILENAME CODE ------------LOGICAL RECORD----------- ----SPACE----
SIZE TYP EOF LIMIT R/B SECTORS #X MX
EDINPUT 256B VA 5 10000 1 16 1 * (TEMP)
:print edinput
text file1
find "patt1"
delete
keep
exit
:editor <edinput >$null
This example demonstrates how a user might use CIOR and the ECHO command
to create and write records to a temporary file. Redirection of the
first ECHO command will either create EDINPUT if it doesn't already exist
as a temporary file or open the existing EDINPUT file in preparation for
overwriting it. The other ECHO commands will append to EDINPUT. This
temporary file is then used as input to EDITOR.
Output redirection behaves differently if the output destination is a
device file, such as a spoolfile, versus a normal file. For example:
:purge abc
:showme >abc
:showout >>abc
:file lp602;dev=epoc;env=lp602.hpenv.sys
:showme >*lp602
:showout >>*lp602
In the first example, ABC is created and the SHOWME output is written to
this new temporary file. ABC is then closed. For the SHOWOUT, ABC is
reopened for APPEND access, and the output of the SHOWOUT is appended to
ABC. This produces a file containing the output of a SHOWME followed by
the output of a SHOWOUT. In the second example, however, a new spoolfile
is created for the SHOWME and the output written to it. When the SHOWME
is finished, the spoolfile is closed and will become ready to print. The
SHOWOUT does the same thing resulting in a new spoolfile being created
and the output being written to it. This different behavior is due to
the fact that a spoolfile is completed and made ready for printing when
it is closed. A spoolfile cannot be reopened.
It should be pointed out that the redirection specification is stripped
off the command line after variable and expression substitution and
before the command is actually executed. This is so that command
executors and User Commands are not affected by this special string.
(Note that variable substitution consists of substituting the value of a
variable or parameter for its name. Expression substitution consists of
substituting the result of an expression into the command line. These
two operations are referred to as string substitution.) With an MPE
version prior to 2.1, the following command would produce an error.
:editor <myfile >$null newfile
^
FIRST CHARACTER IN FILE NAME NOT ALPHABETIC. (CIERR 530)
With CIOR, this command will work fine because both redirection
specifications, <myfile and >$null, will be stripped off the command
line. This would leave editor newfile to be parsed and executed.
However, the input would be read from MYFILE and the output would be sent
to $NULL. (The OFFLINE output would still go to NEWFILE.)
This example also points out the fact that redirection specifications,
whether for input or output redirection, can appear almost anywhere on
the line. The only place they can't appear is before the command name.
Redirection of I/O may be done even if I/O has already been redirected.
For example, assume we have a command file named SHOW containing the
following:
parm showdest="$STDLIST"
showme
showout >!showdest
showvar
showjob >>!showdest ;job=!hpuser.!hpaccount
Invoking the command as follows will demonstrate some capabilities of
CIOR:
:show outfile >*lp602
Before the SHOW command file is executed, the $STDLIST of the CI will be
changed to a new LP602 spoolfile. The SHOWME will be written to this
spool file. The SHOWDEST parameter will have a value of outfile. When
the SHOWOUT is processed, string substitution will occur first, resulting
in:
showout >outfile
At this point, the current state of the spoolfile will be saved, and
OUTFILE will be opened (new or APPEND, as appropriate). The SHOWOUT
output will be written to OUTFILE, and OUTFILE will be closed. The
SHOWVAR output will then be written to the same spoolfile, since its
state was saved. Finally, the SHOWJOB output will be appended to
OUTFILE. This stacked redirection will provide the user much flexibility
in the way he or she can use CIOR.
At the completion of this example there would be a new, TEMP file named
OUTFILE which would contain the output of a SHOWOUT followed by the
output of the command, showjob ;job=SCOTT.UI (if the user executing the
SHOW command file was SCOTT.UI). There would also be an LP602 spoolfile
containing the output of a SHOWME and the output of a SHOWVAR.
Notice, also, the default value for the SHOWDEST parameter. The
capability to specify >$STDLIST or <$STDIN as redirection specifications
is provided to handle this type of parameter defaulting. As an example,
if no parameter is given, the SHOWOUT command becomes showout >$STDLIST
after string substitution. The redirection specification, $STDLIST is
stripped off of the command line, but no redirection is done, since none
is necessary. <$STDIN behaves similarly.
This example also illustrates why the scan for redirection specifications
is done after string substitution. If the redirection scan were done
before string substitution, or at the same time, the user couldn't
specify an input or output redirection file using parameters or
variables, as is done in the above example. This ordering also allows
the following:
:setvar dest ">abc"
:listf !dest
After string substitution, the LISTF would become listf >abc. The
redirection scan would then find the >abc and the output would be
redirected to the file ABC.
Expression substitution is also done in the string substitution pass and
would, therefore, also be performed before the redirection scan. This
feature might be used as follows to dynamically specify a redirection
specification:
:listf ![input('Enter the fileset to be displayed:')],6 &
>![input('Enter the file name for the output of the LISTF:')]
During the string substitution scan, the user will be prompted for the
fileset using the evaluator function, INPUT(). The string entered, say
abc@ef, will be substituted into the line. Next the user will be
prompted for an output file name. This value, outfile for example, will
be substituted into the line. After the string substitution pass the
command line will be:
:listf abc@ef,6 >outfile
Next, the output will be redirected, and then the LISTF will be executed.
MPE XL currently supports some forms of I/O redirection. The following
exampleswill illustrate the relationship between CIOR and the redirection
currently available.
The :RUN command creates a process to run the program requested. It also
allows the user to redirect the input and/or output of the process when
it is run. A process created in this way will inherit the same input
source and output destination of its parent process unless something
different is requested through the command itself. For example:
:run prog;stdin = foo < bar > bar2
Since the user is requesting input redirection through CIOR, the input of
the CI will be redirected to the file BAR and the output of the CI to the
file BAR2. If this multiple redirection proceeds without error, the :RUN
command will be executed. This will create the process in which PROG
will run. The input of that process will be redirected to the file FOO
as requested through the STDIN= parameter of the RUN. However, the output
of the PROG process will remain redirected to BAR2, the same output
destination of the CI that created it. No input will be taken by PROG
from BAR and so the input redirection using CIOR was extraneous.
Another type of redirection currently supported by MPE XL is through
commands such as :LISTF.
:listf @.@.@;bigfile > notsobig
This is also a case of an unnecessary use of CIOR. The output of the CI
will be redirected to the file NOTSOBIG. The output of the LISTF will be
sent to BIGFILE by the LISTF command itself. The command, listf
@.@.@;bigfile, doesn't produce any $STDLIST output and so NOTSOBIG will
not contain any output.
One final example:
:listf nonexist;foo >bar
This example is very similar to the preceding example except that the
LISTF will get an error. FOO will be created by LISTF, but will contain
no output. BAR will be created by CIOR and will contain the following
error:
NON-EXISTENT FILE. (CIERR 907)
To summarize the main points of this section:
* >filename is used to redirect output of a command to filename.
* >>filename is used to append output of a command to filename.
* <filename is used to redirect input of a command from filename.
* Spaces are allowed between the redirection specification and the
filename.
* There are defaults for the opening of the files to or from that
output or input that is being redirected.
* Output redirection behaves differently if the output destination
is a device file, such as a spoolfile.
* The redirection specification may appear anywhere on a command
line after the command name. It is stripped off the command line
before it is parsed or executed.
* Redirection may be stacked. A redirected command file may contain
a redirected command.
* >$STDLIST (and >>$STDLIST) and <$STDIN are supported.
* The scan for redirection indicators is performed after string
substitution.
* A process created by the CI inherits its parent's input and output
unless something different is requested through the command
itself.
* CIOR only redirects output to $STDLIST or input from $STDIN. Any
other currently supported form of redirection is not affected.
HPSTDIN and HPSTDLIST
Two read-only, predefined MPE XL string variables are provided to reflect
the state of I/O redirection. These variables can be used within user
commands or programs that need to detect if their input or output has
been redirected. HPSTDIN will default to the string value, $STDIN.
HPSTDLIST will default to the string, $STDLIST. These values will also
indicate that input or output is not currently redirected. If input is
redirected, HPSTDIN will contain the filename of the file to which input
has been redirected. If input has been redirected through a file
equation backreference, HPSTDIN will contain the formal file designator
from the file equation. Similarly, HPSTDLIST will contain the filename
or formal file designator of the file or file equation to which output
has been redirected.
For example, consider a command file called IORSTATE that contains the
following:
if hpstdin = '$STDIN' then
echo No input redirection.
return
endif
echo $STDIN is redirected to !hpstdin. >>iorlog
if hpstdlist <> '$STDLIST' then
echo $STDLIST is redirected to !hpstdlist >>iorlog
endif
setvar i 1
continue
input a
while i <= finfo(hpstdin,'eof') do
echo Record !i = ..!a..
setvar i i+1
continue
input a
endwhile
Suppose IORSTATE is executed as follows:
:file lp602;dev=epoc;env=lp602.env.sys
:iorstate >*lp602 <input.pub.sys
Assuming INPUT.PUB.SYS contains the two records:
Line 1 of input
Line 2 of input
the following lines will be appended to the file IORLOG:
$STDIN is redirected to INPUT.PUB.SYS
$STDLIST is redirected to LP602
The following lines will be in an LP602 spoolfile:
Record 1 is ..Line 1 of input..
Record 2 is ..Line 2 of input..
BREAK and CIOR
One of the goals of CIOR is to ensure that a command that has been
redirected behaves the same as that same command would if it weren't
redirected. The obvious exception is that its input or output would be
redirected. However, commands and programs that can be interrupted using
the BREAK key should still be interruptable. When BREAK is hit, the user
must be able to interact with a CI that does NOT have its input or output
redirected.
If the command that was redirected is a process command, such as EDITOR,
FCOPY, or any program which has been RUN, the input and output will be
redirected back to the terminal. When the broken process is resumed, the
redirection will be reinstated.
If the command that was redirected is not a process command, such as
LISTF or PRINT, the command will be terminated, and the input and output
will be restored to the terminal.
It should also be mentioned that CIOR is available in BREAK mode.
File Limitations
The following limitations exist with CIOR:
* Redirection should not be done to a file using Exclusive access.
If I/O is redirected to such a file, stacked redirection will not
be supported. Neither will commands that result in a process
creation.
* Redirection should not be done to a NEW file. If I/O is
redirected to such a file, stacked redirection will not be
supported. Neither will commands that result in a process
creation.
* Tape device files cannot be used for CIOR.
* KSAM files cannot be used for CIOR.
* The NOWAIT option is allowed only on MSG files.
COMPATIBILITY SPECIFICATIONS
Since CIOR gives a special significance to a certain sequence of
characters, namely >filename, >>filename or <filename, there is a
possibility for incompatibility between the MPE XL 2.1 CI and previous
versions. This could become an issue if a user were to have a job stream
or User Defined Command (UDC) that contained a command that worked on
earlier releases and ceased to work with MPE XL 2.1. To address this
possibility, the places that CIOR may be used have been restricted in
several ways, and a workaround for any remaining problems has been
provided.
CIOR is not applied to every command. The greater-than and less-than
signs are used as redirection indicators. They are also used as the
greater-than and less-than signs in expressions in the IF, ELSEIF, WHILE,
CALC, SETJCW and SETVAR commands. It would be unfortunate if CIOR were
done on the following command:
:if abc>cde then
Because the output, which would only be an *** EXPRESSION TRUE or ***
EXPRESSION FALSE message, would be redirected to a newly created file,
CDE. The command resulting from CIOR would be:
:if abc then
This may or may not be valid but would probably not be what the user had
intended. For this reason, no redirection scan is done on these
commands: IF, ELSEIF, WHILE, CALC, SETJCW and SETVAR.
CIOR will not be attempted on the COMMENT command. This is just to
streamline the execution of COMMENT, since it takes no input and produces
no output. Other commands, such as BUILD, which take no input and
produce no $STDLIST output, will still allow CIOR.
The TELL, TELLOP and WARN commands take no input and produce no output,
so CIOR is not of much use on them (with the possible exception of
capturing errors). However, they take a message as a parameter. The
message in one of these commands can contain any character sequence.
This increases the likelihood that an existing customer job stream, UDC
or command file will have occurrences of these commands with character
sequences which would be interpreted by the CI as CIOR redirection
specifications. This could result in errors such as:
:tell @.testacct <ERROR: Check test output>
This would result in an error (input file nonexistent) unless a file
called ERROR existed, in which case input would be redirected to that
file. In either case, this was not the intent of the TELL. Since CIOR is
not useful on these three commands and they can cause compatibility
problems, CIOR is not available on them. CIOR is also not available on
the REMOTE command because the command following remote may not support
CIOR (such as, REMOTE IF).
Another place where CIOR will not be applied is within matching quotes on
any command line. Unmatched quotes will not affect CIOR. Since INFO
strings on the RUN command are quoted, this restriction will reduce the
possibility of the CI mistaking input to a program as a redirection
specification.
The following command redirects the output of the CI to $NULL and then
runs CI.PUB.SYS, sending it an INFO string containing showme >showfile.
:ci.pub.sys 'showme >showfile' >$null ,3
The next command redirects the output of the CI to the file OUT and then
executes WIERDUDC with three parameters: a', 5 and 4.
:wierdudc a', >out 5,4
Finally, CIOR will not search for specifications within matching square
brackets. This is necessary because commands allowing selection
equations, likeLISTSPF, contain simple expressions within square
brackets. Selection equations can contain the '<', '>' and '<>'
characters followed by strings that could be valid filenames. CIOR would
consider those to be input or output redirection and so must not search
within square brackets. This should not limit the usability of CIOR
since there is really no reason to put redirection specifications within
square brackets.
There may still be situations where the automatic scan for I/O
redirection will change the behavior of a command. At these times the
user will wish to enter a string that looks like a redirection
specification but not have it treated as one. For example, suppose the
user was constructing a command file to explain how to use I/O
redirection that contained the following ECHO command:
:echo The way to redirect $STDLIST is to use the construct, >filename.
If the user couldn't specify that this redirection specification was,
indeed, not a redirection specification, the string "The way to ... the
construct, " would be written to the newly created file with the name
FILENAME. To handle this problem, a technique similar to that used in
string substitution is used: preceding the special character by an
exclamation point. For example, the above example becomes:
:echo The way to redirect $STDLIST is to use the construct, !>filename.
This results in the display:
The way to redirect $STDLIST is to use the construct, >filename.
The following examples illustrate the use of the exclamation point in
escaping the special nature of the !, >, and <:
:echo The way to append output to a file is the construct, !>>filename.
The way to append output to a file is the construct, >>filename.
:echo The way to redirect $STDIN is to use the construct, !<filename.
The way to redirect $STDIN is to use the construct, <filename.
:echo The way to dereference a variable is to use the construct, !!varname.
The way to dereference a variable is to use the construct, !varname.
:echo This is how to escape output redirection, !!!>filename.
This is how to escape output redirection, !>filename.
:echo This is how to escape !>'s by themselves.
This is how to escape >'s by themselves.
$STDERR AND CIOR
A new special file in the same family with $STDIN and $STDLIST has been
enabled. This new special file, $STDERR, is opened for every process to
the original $STDLIST destination, namely, the terminal for a session or
the output spoolfile for a job.
A change has been made in the CI to optionally write all CI error
messages to $STDERR. This allows output of a command or group of commands
to be separated from the error messages. This also facilitates the
display of an error message if end of file is encountered on the file to
which output has been redirected. In addition to the error message, a
caret, and if necessary the command image, will be displayed to $STDERR.
Enabling this separation of output from error messages is accomplished
with the new CI predefined variable, HPERRSTOLIST. If this variable is
TRUE, all error and warning messages from the CI are written to $STDLIST.
This is the default. If this variable is set to FALSE, all CI error and
warning messages are written to $STDERR.
ERROR HANDLING
There are several issues concerning the handling of errors that occur
before redirection of output, during I/O redirection, and after output
redirection. Warnings are handled in the same way errors are handled.
The CIOR scan for redirection specifications is performed immediately
following the string substitution pass. The display of any warnings that
occur during string substitution is performed before redirection.
If an error occurs during the redirection of input or output, it is
displayed and the command terminated. If both input and output are being
redirected, input is redirected first. If the input redirection is
successful, but an error occurs during output redirection, the input is
redirected back to its original file. The error is then displayed and
the command terminated.
Any CI errors that occur once output has been successfully redirected are
written to the redirected file, unless HPERRSTOLIST is set to FALSE. If
the HPERRSTOLIST variable is FALSE, errors are written to $STDERR which
typically is the terminal for sessions.
The end of a file that the output has been redirected to may be reached.
If this is detected by the CI, the error related to this condition will
be reported to $STDERR.
NOTE This error condition may not be detected immediately, or at all.
Currently, some commands do not detect this problem.
A UDC whose output has been redirected will, of course, not display any
errors. All error or warning messages are sent to the redirected
destination. To determine if any errors occurred, CIERROR may be
checked. This variable contains the error number of the last error
encountered during the execution of the UDC.
MPE/iX Communicators