1  PIPE
   Executes one or more DCL command strings from the same command
   line. The PIPE command enables you to perform UNIX style command
   processing, such as command pipelining, input/output redirection,
   and conditional and background execution.

   Format

     PIPE  command-sequence [separator command-sequence]...
 

2  Parameters
 

command-sequence

   A DCL command, a pipeline, or a subshell:

   o  DCL command

      A DCL command string, which can include qualifiers,
      parameters, keywords, and values.

   o  Pipeline

      A pipeline is a sequence of pipeline-segment commands
      connected by pipes, represented by the vertical-bar (|)
      separator. A pipeline-segment command is a DCL command that
      appears in a pipeline. The pipe connects the SYS$OUTPUT of one
      pipeline-segment command to the SYS$INPUT of the next command.
      The format of a pipeline is as follows:

      pipeline-segment-command | pipeline-segment-command [|...]

   o  Subshell

      A subshell is one or more command sequences separated by
      separators and enclosed in parentheses. The format of a
      subshell is as follows:

      (command-sequence [separator command-sequence]...)

   Input/output redirection is allowed in a command sequence. The
   command before an angle bracket (> or <) redefines its SYS$INPUT,
   SYS$OUTPUT, or SYS$ERROR during execution. You cannot use angle
   brackets (<>) to represent a directory specification in a PIPE
   command because the PIPE command interprets angle brackets as
   input/output redirection syntax.
 

separator

   Determines the processing action of the command sequences
   specified in a PIPE command. The valid PIPE separators are
   described in the following table.
 

   Separator  Action

   |          Key pipe separator. The pipe connects the SYS$OUTPUT of
              one pipeline-segment command to the SYS$INPUT of the
              next command.
   ;          Sequential execution. The command sequence following
              the semicolon (;) is executed after the preceding
              command sequence is completed. You must precede
              this separator with a blank space; otherwise, it is
              parsed as the Record Management System (RMS) file
              specification version number delimiter.
   &&         Conditional execution (upon success). The command
              sequence following the double ampersand (&&) is
              executed only if the preceding command sequence
              succeeds.
   ||         Conditional execution (upon failure). The command
              sequence following the double vertical bar (||) is
              executed only if the preceding command sequence fails.
   &          Background execution. All command sequences that
              precede the ampersand (&) are executed asynchronously
              in a subprocess environment. The & separator is similar
              to the SPAWN/NOWAIT command.

              Note: Any ampersand that precedes a character string
              without spaces in between is parsed as a conventional
              DCL symbol substitution expression rather than the
              background execution syntax.
   @TEE       Command file, TEE.COM. Used for redirecting output to
              two targets (for example, one output is directed to
              the next stage in pipeline, and the other to a file).
              See the Examples section for an example of how to use
              TEE.COM.

   In a PIPE command line, the "&" has the highest precedence,
   followed by "|", ";", "&&", and "||", which have equal
   precedence.
 

2  Description
   The PIPE command allows you to perform UNIX style command
   processing by executing multiple DCL commands in a single command
   line. You can use the PIPE command to execute DCL commands in a
   number of ways:

   o  Multiple command execution

      Multiple DCL commands are specified in a single PIPE command
      and executed sequentially. The syntax for multiple command
      execution is as follows:

      PIPE   command-sequence ; command-sequence [; command-sequences]...

   o  Conditional command execution

      A command sequence is executed conditionally depending on the
      execution result of the preceding command sequence.

      Using the following form, command-sequence2 executes if, and
      only if, command-sequence1 succeeds:

      PIPE   command-sequence1   &&   command-sequence2

      Using the following form, command-sequence2 executes if, and
      only if, command-sequence1 fails:

      PIPE   command-sequence1   ||   command-sequence2

   o  Pipeline command execution

      A pipeline is formed by connecting DCL commands with pipes as
      follows:

      PIPE pipeline-segment-command | pipeline-segment-command [|...]

      Each pipeline-segment command runs in a separate subprocess
      with its SYS$OUTPUT connected to the SYS$INPUT of the next
      pipeline-segment command. These subprocesses execute in
      parallel; however, they are synchronized to the extent that
      each pipeline-segment command, except the first, reads the
      standard output of its predecessor as its standard input. A
      pipeline finishes execution when the last pipeline-segment
      command is done.

      It is very common to use filter applications in a pipeline.
      A filter application is a program that takes data from
      SYS$INPUT, transforms it in a specific way, and writes it
      to SYS$OUTPUT.

   o  Subshell execution

      Command sequences can be executed in a subprocess environment
      by using the subshell execution form:

      PIPE   ( command-sequence [separator command-sequence]... )

      The command sequences in a subshell are executed in a
      subprocess environment. DCL waits for the subshell to complete
      before executing the next command sequence. The ( ) separator
      is similar to the SPAWN/WAIT command.

   o  Background execution

      Command sequences can be executed in a subprocess environment
      by using the following form:

      PIPE  command-sequence [ separator command-sequence]...  &

      DCL does not wait for the command sequences to finish. Control
      passes back to DCL once the background subprocess is created.

   o  Input/output redirection

      A command sequence can redirect its SYS$INPUT, SYS$OUTPUT,
      or SYS$ERROR to a file during execution of the command as
      follows:

      To redirect SYS$INPUT:

         PIPE    command-sequence < redirected-input-file

      To redirect SYS$OUTPUT:

         PIPE    command-sequence > redirected-output-file

      To redirect SYS$ERROR:

         PIPE    command-sequence 2> redirected-error-file

      A pipeline-segment command can also redirect its SYS$INPUT,
      SYS$OUTPUT, or SYS$ERROR; however, SYS$OUTPUT redirection
      is allowed only for the last pipeline-segment command, and
      SYS$INPUT redirection is allowed only for the first pipeline-
      segment command.

   You can interrupt a PIPE command by pressing Ctrl/Y. If the
   PIPE command is executing in a pipeline or a subshell command
   sequence, the command sequence and the PIPE command are deleted.
   In this case, a CONTINUE command entered immediately after the
   interrupt will not resume the execution of the PIPE command.

   If the PIPE command is executing a command sequence other than
   a subshell or a pipeline command sequence, DCL behaves as if the
   command sequence were entered as a DCL command without the PIPE
   command verb and interrupted by Ctrl/Y. See the OpenVMS User's
   Manual for more information on the Ctrl/Y interrupt.

   Each command sequence sets the global symbol $STATUS with a
   returned value after it finishes execution. The return status
   of the PIPE command is the return status of the last command
   performed in the last segment. If all segments fail with some
   kind of error and the last segment returns with success, the
   status returned to DCL is the success.

   When a PIPE command is executed in a command procedure with the
   ON condition processing, the conditional execution of command
   sequences (&&, ||) takes precedence over the action previously
   specified by the ON condition statement.
 

3  DCL_Command_Restrictions
   The PIPE command creates a special execution context for its
   command sequences. The following DCL commands either do not work
   or exhibit new behavior in this context:

   o  PIPE - Nested PIPE commands in the same command procedure
      level are not allowed. There can only be one PIPE command
      context for each command procedure level; however, nested
      PIPE commands at different procedure levels are allowed. For
      example:

       $ TYPE FOO.COM
       $ ! FOO.COM
       $   :
       $ PIPE   ...
       $ :
       $
       $ PIPE    @FOO.COM ; ...

      In this example, the PIPE command inside FOO.COM is allowed
      because it is executed at a different command procedure level.

   o  GOTO and EXIT - These two commands, when executed as PIPE
      command sequences, delete the PIPE command context before
      the GOTO or EXIT command is executed. Any command sequences
      following these two commands in a PIPE command are flushed.

   o  STOP - The STOP command, when executed after a PIPE command is
      interrupted by Ctrl/Y, deletes the PIPE command context.

   o  THEN, ELSE, ENDIF, SUBROUTINE, ENDSUBROUTINE, RETURN, and
      DCL labels - These commands cannot execute as PIPE command
      sequences because it is not possible to realize their
      functions in a PIPE command context.
 

3  Improving_Subprocess_Performance
   A PIPE command can generate a number of subprocesses during
   execution. Often, the applications invoked by command sequences
   do not depend on the process logical names and symbol names.
   In this case, the spawning of subprocesses can be accelerated
   by using the /NOLOGICAL_NAMES and /NOSYMBOLS qualifiers, which
   suppress the passing of process logical names and symbols to the
   subprocesses created by the PIPE command.
 

3  Input_Output_Redirection
   DCL users can use the DEFINE or ASSIGN command to redirect
   SYS$INPUT, SYS$OUTPUT, or SYS$ERROR. Such redirection can be
   created as either the user-mode (using the /USER_MODE qualifier)
   or supervisor-mode (using the /SUPERVISOR_MODE qualifier)
   redirection. A user-mode redirection only affects the environment
   of the next user-mode image.

   In a PIPE command, redirection can be achieved by using the
   redirection syntax. A PIPE command redirection is quite different
   from that created by the DEFINE or ASSIGN command, as follows:

   o  Redirections are created in supervisor mode. This means that
      both user-mode applications and DCL commands are affected by
      the redirections.

   o  The redirected environment only applies to the command
      sequence or the pipeline-segment command that specifies
      the redirection syntax. After the execution of the command
      sequence or pipeline-segment command, the original process
      input/output environment (that is, SYS$INPUT, SYS$OUTPUT, and
      SYS$ERROR) is restored before command execution continues.

   When SYS$OUTPUT is redirected, the redirected output file is
   always created, whether or not the command sequence actually
   writes to SYS$OUTPUT. If a version of a file with the same name
   as the redirected output file already exists, a new version of
   that file is created. (This behavior is the same as using the
   DEFINE or ASSIGN command to redefine SYS$OUTPUT in supervisor
   mode.) Note that the redirected file is created before the
   command sequence is executed. If the redirected file is also
   used in the command sequence, the operation may fail, as in the
   following example:

   $ PIPE SEARCH TRANS.LOG "alpha" > TRANS.LOG

   %SEARCH-W-OPENIN, error opening TRANS.LOG;2 as input
   -RMS-E-FLK, file currently locked by another user

   In this example, a new version of TRANS.LOG is created and opened
   for write access; the SEARCH command then tries to get read
   access to the most recent version of TRANS.LOG instead of the
   expected previous version.

   When SYS$ERROR is redirected, the redirected error file is
   only created when the command sequence actually writes to the
   SYS$ERROR during execution, and there is no existing file with
   the same name as the redirected error file. If a file with the
   same name as the redirected error file already exists, that
   file is opened as the redirected error file. The error output
   generated by this command sequence is then appended to the end
   of the redirected error file. (This behavior is the same as using
   the DEFINE or ASSIGN command to redefine SYS$ERROR in supervisor
   mode.)
 

3  Pipelines_and_TEEs
   This section describes aspects of DCL that function differently
   in the context of a pipeline.

   Some of the following constructs are used in the implementation
   of a TEE.
 

4  Using_SYS$COMMAND
   The SYS$COMMAND of a subprocess is normally the same as its
   SYS$INPUT (if no command procedures are involved). In a
   pipeline, however, the SYS$COMMAND of a subprocess is set to
   the SYS$COMMAND of the parent process instead of to the preceding
   pipe (which is the SYS$INPUT of the pipeline-segment command).
 

4  Using_TEEs_and_SYS$PIPE
   In most cases, input from the pipe can be obtained by reading
   the data from SYS$INPUT; however, when a command procedure is
   invoked as a pipeline segment command, SYS$INPUT is redirected to
   the command procedure file. To obtain data from the pipe inside a
   command procedure, the logical SYS$PIPE can be used.

   The following is an example of a pipeline DCL application
   TEE.COM:

    $ ! TEE.COM - command procedure to display/log data flowing through
    $ !           a pipeline
    $ ! Usage: @TEE log-file
    $
    $ OPEN/WRITE  tee_file 'P1'
    $ LOOP:
    $  READ/END_OF_FILE=EXIT  SYS$PIPE LINE
    $  WRITE SYS$OUTPUT LINE !Send it out to the next stage of the pipeline
    $  WRITE tee_file LINE  ! Log output to the log file
    $  GOTO LOOP
    $ EXIT:
    $  CLOSE tee_file
    $  EXIT

   The PIPE command to use TEE.COM can be:

   $ PIPE  SHOW SYSTEM | @TEE showsys.log | SEARCH SYS$INPUT LEF

   The command procedure TEE.COM is used to log the data flowing
   through the pipeline. It reads in the data from SYS$PIPE instead
   of SYS$INPUT.
 

4  Image_Verification_in_a_Pipeline
   In a pipeline, image verification is turned off by default, even
   when the command SET VERIFY=IMAGE is executed before the PIPE
   command is entered. This prevents duplication of data records
   going through the pipeline.

   To turn on image verification in a pipeline, an explicit SET
   VERIFY=IMAGE command must precede the pipeline segment command.
   You can use a subshell to do this, as follows:

   $ PIPE ... | (SET VERIFY=IMAGE ; ...)  | ...
 

4  File_Access_Methods_in_a_Pipeline
   A pipeline segment command can only use the RMS sequential file
   access method to read and write to the pipes. Certain OpenVMS
   utilities may access their input and output files using methods
   other than sequential access. These operations are not supported
   in a pipeline, and will fail, as in the following example:

   $ PIPE CC/NOOBJ/NOLIS TEST.C | SEARCH SYS$INPUT/WIND=(1,1) "%cc-w-"

   %SEARCH-F-RFAERR, RMS error using RFA access
   -RMS-F-RAC, invalid record access mode

   In this example, the /WINDOW qualifier for the SEARCH command
   requires the relative file access method.
 

2  Qualifiers
 

/LOGICAL_NAMES

      /LOGICAL_NAMES (default)
      /NOLOGICAL_NAMES

   Copies process logical names and logical name tables to the
   subprocess of a command sequence. By default, all process logical
   names and logical name tables are copied to the subprocess except
   those explicitly marked CONFINE or created in executive or kernel
   mode.
 

/PRIVILEGES

      /PRIVILEGES={CURRENT|AUTHORIZED}

   Determines whether the subprocess inherits the current
   process's current or authorized privileges as its authorized
   privileges. By default, the authorized privilege mask for
   the subprocess is taken from the current privileges of its
   creator. (This corresponds to /PRIVILEGES=CURRENT.) If the
   /PRIVILEGES=AUTHORIZED qualifier is specified, the subprocess's
   authorized privileges are taken from the creator's authorized
   privileges.
 

/SYMBOLS

      /SYMBOLS (default)
      /NOSYMBOLS

   Determines whether global and local symbols (except $RESTART,
   $SEVERITY, and $STATUS) are passed to the subprocess. $RESTART,
   $SEVERITY, and $STATUS symbols are never passed to the
   subprocess.
 

/TRUSTED

      /TRUSTED
      /NOTRUSTED

   Indicates that the PIPE command input originates in a trusted
   command procedure. PIPE commands are not allowed in CAPTIVE
   accounts. The /TRUSTED qualifier provides a way for properly
   written captive command procedures to perform PIPE operations
   when the command input originates in the captive command
   procedure where it can be trusted. For more information about
   trusted command procedures, see the VSI OpenVMS Guide to System
   Security.
 

2  Examples

   1.$ PIPE SHOW SYSTEM | SEARCH SYS$INPUT HIB

     This example uses the pipeline function to identify all
     hibernating processes on the system in one command.

   2.$ PIPE RUN TEST | SORT/SPECIFICATION=TEST.SRT SYS$INPUT SYS$OUTPUT -
        | DIFF SYS$INPUT  TEST.BENCHMARK

     This example uses the pipeline function to run a test, sort
     the result, and compare the result to the benchmark file in
     a single command without generating unnecessary intermediate
     files.

   3.$ PIPE  ( SET DEF WRK$:[WORK] ; RUN REPORT ) | MAIL SYS$INPUT SMITH

     This example shows one way a subshell can be specified as a
     pipe segment command in a pipeline.

   4.$ more :== TYPE/PAGE=SAVE SYS$INPUT
     $ PIPE    ANA/RMS PAGE.TXT | more

     Check RMS File Integrity                26-DEC-2001 16:12:00.06  Page 1
     SYS$SYSDEVICE:[TEST]PAGE.TXT;2

     FILE HEADER

         File Spec: SYS$SYSDEVICE:[TEST]PAGE.TXT;2
         File ID: (4135,58220,0)
         Owner UIC: [PIPE]
         Protection:  System: RWED, Owner: RWED, Group: RE, World:
         Creation Date:   26-NOV-2001 16:08:50.05
         Revision Date:   26-NOV-2001 16:09:09.06, Number: 1
         Expiration Date: none specified
         Backup Date:     none posted
         Contiguity Options:  none
         Performance Options: none
         Reliability Options: none
         Journaling Enabled:  none

     RMS FILE ATTRIBUTES

     RETURN/SPACE=More, PREV/NEXT=Scroll, INS/REM=Pan, SELECT=80/132, Q=Quit

     This example shows the use of the /PAGE qualifier within a
     pipeline. The /PAGE function exists in a number of other DCL
     commands as well, and can be used similarly in conjunction with
     the PIPE command to form other useful tools.

   5.$ ! TEE.COM - command procedure to display/log data flowing through
     $ !           a pipeline
     $ ! Usage: @TEE log-file
     $
     $ OPEN/WRITE  tee_file 'P1'
     $ LOOP:
     $  READ/END_OF_FILE=EXIT  SYS$PIPE LINE
     $  WRITE SYS$OUTPUT LINE ! Send it out to next stage of the pipeline
     $  WRITE tee_file LINE  ! Log output to the log file
     $  GOTO LOOP
     $ EXIT:
     $  CLOSE tee_file
     $  EXIT

     This is an example of a pipeline DCL application TEE.COM.

     The PIPE command to use TEE.COM can be:

       $ PIPE  SHOW SYSTEM | @TEE showsys.log | SEARCH SYS$INPUT LEF

     The command procedure TEE.COM is used to log the data flowing
     through the pipeline. It reads in the data from SYS$PIPE
     instead of SYS$INPUT.

   6.$ CD_WORK :== PIPE   SAVE_DIR=F$DIRECTORY() ; SET DEFAULT FOO:[WORK]
     $ BACK  :== SET DEF 'SAVE_DIR'
     $
     $ CD_WORK  ! Switch to working directory
     $     :
     $     :
     $ BACK     ! Switch back to home directory

     $ GET_RECORD :== PIPE READ/END_OF_FILE=CLEANUP IN RECORD ; -
                 F$EDIT(RECORD, "COMPRESS, TRIM")
     $
     $ OPEN IN EMPLOYEE.DAT
     $ LOOP:
     $ GET_RECORD
     $    :
     $    :
     $ GOTO LOOP
     $
     $ CLEAN_UP:
     $    :

     This example shows two simple uses of multiple commands with
     symbol definitions to build useful tools in command procedures.

   7.$ PIPE cc foo.c && link foo

     If the compilation does not generate any error, the object
     file is linked to produce an executable image. If the program
     compilation generates an error, the linking step is skipped.

   8.$
     $ PIPE RUN COLLECT_DATA.EXE || GOTO CLEAN_UP
     $   :
     $  :
     $ EXIT
     $
     $ CLEAN_UP:
     $ :
     $  :

     Using conditional command execution, it is easy to set up
     simple error handling control flow in a command procedure.
     If the image COLLECT_DATA fails, control is directed to CLEAN_
     UP.

   9.$ PIPE COPY LARGE_FILE.DAT REMOTE"user password"::[DESTINATION]*.*  &

     This PIPE command creates a background process to handle the
     copying of the large file.

   10$ PIPE (SET DEF [.DATA_DIR] ; BACKUP  DATA.SAV/SAV [...]) ; RUN FOO

     The subshell command sequence is done in a subprocess. This
     means that changing a process-specific characteristic (for
     example, the default directory) will not affect the current
     process after the subshell is finished. In this example, the
     save set is restored in a subdirectory to provide the necessary
     data to run the program FOO.

   11$ RSH 0 PIPE SH DEC/FI | SH LOG/PR

     LNM$PROCESS_TABLE

       "SYS$COMMAND" = "_NODE$MPA24:"
       "SYS$DISK" = "SYS$SYSDEVICE:"
       "SYS$ERROR" = "_BG9930:"
       "SYS$INPUT" [super] = "_BG9930:"
       "SYS$INPUT" [exec] = "_NODE$MPA24:"
       "SYS$OUTPUT" [super] = "_BG9930:"
       "SYS$OUTPUT" [exec] = "_BG9930:"
       "SYS$PIPE" = "_NODE$MPA24:"
       "TT" = "_MPA24:"

     This example shows how SYS$PIPE and SYS$OUTPUT might differ.
 

