DCL_PIPE.BCKi DCL_PIPE.BCKOBACK *.* CMKRNL::[ANONYMOUS.SAVE_SETS]DCL_PIPE.BCK/NOCRC/GROUP:0/BLOCK=8192/SAV AWPSYS  LAlV5.1 _VAXB::  V5.0 (*[DCOLIB.TSLIB_PROGS.PIPE]AAAREADME.TXT;1+,a./ 4C-`0123KPWO56Aѥ7Tڿ*189f1G HJ?PIPE a Ultilty to allow unix like filtering and redirection of  Standard input or output. Date: 19 April 1985 Author: Andrew W. Potter% Rochester Institute of Technology One Lomb Memorial Drive Rochester, New York 146325 Copyright 1987 by Rochester Institute of Technology8 Permission is granted to freely modify and distribute C (but NOT SELL) this software provided this copyright> notice is included in all versions distributed. Installation:> 1) Build PIPE. (If you have fortran) Using BUILD_PIPE.COM8 If you dont have fortran just link the supplied objects as shown in BUILD_PIPE.COM, 2) Place PIPE in some utility directory.A 3) Pipe can be defined SYSTEM wide by adding the supplied CLD5 to the system DCLTABLES with the following commands. $ INSTALL == "$INSTALL/COMMAND"4 $ SET COMMAND/TABLES=SYS$COMMON:[SYSLIB]DCLTABLES -7 /OUTPUT=SYS$COMMON:[SYSLIB]DCLTABLES pipe( $ INSTALL REPLACE SYS$LIBRARY:DCLTABLES - OR -0 PIPE may be simply invoked as a foreign command" $ PIPE == "$DISK:[DIRECTORY]PIPE" 4) install PIPE.HLP0 $ LIBRARY/HELP SYS$HELP:HELPLIB PIPE.HLP To use pipe:3 $ PIPE command1 standard_out EX:1 $ pipe show system | search sys$input " COM "4 Does a SHOW SYSTEM of Computable processes only.: $ pipe show system | search sys$input " COM " >COM.DAT ? Does the same thing but places the output in COM.DAT7 Look at the help entry for pipe for other examples and! restrictions on the use of pipe.#*[DCOLIB.TSLIB_PROGS.PIPE]EXIT.FOR;1+,b./ 4N-`0123KPWO567*189f1G HJ*;* This is an example program that demos the use of TERMINALA* AST routing mechanism. It also demos a mechanism to read F* from the TERMINAL in NOECHO mode. (good for getting passwords)*E* This program is in effect a terminal locker and demos the following* system routines:*'* LIB$DISABLE_CTRL, LIB$ENABLE_CTRL** SYS$QIOW** SYS$UNWIND** SYS$DCLEXT** LIB$ESTABLISH** implicit integer(a-z)** character*10 prompt /'Password: '/ character*30 password integer l_pass integer*4 tt_chan common/channel/ tt_chan$ integer*4 mask/'02000000'X/,oldmask common /ctrl/ mask,oldmaskA call sys$assign('TT',tt_chan,,) ! assign TTCHAN for terminalF ! AST and NOECHO read QIOs*< Call lib$disable_ctrl(mask,oldmask) ! Tell DCL,"I'll HandleI ! all the CTRL/Ys"*: call xcon_init ! set up exit handler*@ Call Enable_Ctrl_C ! enable my ASTs for CTRL/C1 Call Enable_Ctrl_y ! and CTRL/Y password = ' '*+ do while (password(1:5).ne.'OK_OK'). call lib$put_output('Get it right!')" call lib$put_output(' ')/ call getpass(password,prompt,l_pass,tt_chan)" call lib$put_output(' ') end do*+ call lib$put_output('By Golly you did it') call lib$put_output(' ')*B: call lib$put_output('About to call exit...Exit handler?') call lib$put_output(' ') endL***************************************************************************** *L* Routines Enable_Ctrl_C and Ctrl_Y are the same but enable separate *)* ASTs for CTRL_y and CTRL_c ** *L**************************************************************************** Subroutine Enable_Ctrl_CL**************************************************************************** Implicit Integer (a-z) integer tt_chan common /channel/ tt_chanD External Ctrl_C_Rout ! Where to go when ctrl/c is hit Include '($IODEF)'A istat=SYS$QIOW(,%VAL(TT_Chan),%VAL(IO$_SETMODE.OR.IO$M_CTRLCAST)' + ,,,,Ctrl_C_Rout,,%VAL(3),,,)+ if (.NOT.istat) Call LIB$STOP(%VAL(istat)) Return End*K****************************************************************************% Subroutine Enable_Ctrl_YK*************************************************************************** Implicit Integer (a-z) integer tt_chan common/channel/ tt_chanB External Ctrl_Y_Rout ! Where to go when ctrl/y hit Include '($IODEF)'A istat=SYS$QIOW(,%VAL(TT_Chan),%VAL(IO$_SETMODE.OR.IO$M_CTRLYAST)' + ,,,,Ctrl_Y_Rout,,%VAL(3),,,)+ if (.NOT.istat) Call LIB$STOP(%VAL(istat)) Return EndI************************************************************************* * *I* These routines is entered automatically when CTRLc or CTRLy is hit * * *I************************************************************************* Subroutine Ctrl_C_RoutI***************************************************************************?* This is where control is passed when a user hits Ctrl C**& call lib$put_output('**** ouch ****') call sys$unwind()? call enable_ctrl_c ! reenable ctrl c ast return End*I*************************************************************************** Subroutine Ctrl_Y_Rout**0 call lib$put_output('**** REALLY OUCH!!! ****')*E* call sys$unwind to reset the stack to the beginning-* of the prior procedure call** call sys$unwind()@ call enable_ctrl_y ! renable ctrl y ast return EndE*********************************************************************0 subroutine getpass(password,prompt,l_pass,chan)E********************************************************************* implicit integer*4(a-z) integer*2 chan3 external io$_readprompt,io$m_noecho,io$m_trmnoecho* character*30 password,lpassword' character*(*) prompt,lprompt*50,crlf*2 crlf = char(13)//char(10) password(1:30) = ' '*' call str$trim(lprompt,prompt,l_prompt)) lprompt = crlf//lprompt(1:l_prompt)//' ' l_prompt = l_prompt+3*8 func_code = %loc(io$_readprompt) .or. %loc(io$m_noecho)*F stat =sys$qi  DCL_PIPE.BCKb`#[DCOLIB.TSLIB_PROGS.PIPE]EXIT.FOR;1NU8  ow(,%val(chan),%val(func_code),,,,%ref(lpassword),C 1 %val(30),,,%ref(lprompt),%val(l_prompt))* locterm = 0$ locterm = index(lpassword,char(10)) if (locterm.gt.0) then, lpassword(locterm:locterm) = ' ' lpassword(locterm:30) = ' ' endif*$ locterm = index(lpassword,char(13)) if (locterm.gt.0)then% lpassword(locterm:locterm) = ' ' lpassword(locterm:30) = ' ' endif*) call str$trim(password,lpassword,l_pass)* return* endH************************************************************************** Exit control for general use** there are three routines: *E* XCON_INIT Call this first thing in the program to establish* exit trapping.*K* XCONOFF Call this to turn off exit control before you exit 4* the program normally. ( this prevents FINAL from%* running when you do a "CALL EXIT"*A* FINAL This subroutine is what is actually called when2* any exit condition occurs.*N****************************************************************************** subroutine xcon_init external final4 integer pointer, exitadr, argcount, statadr, status> common /exithand/ pointer, exitadr, argcount, statadr, status0c initialize necessary values for exit control/c This is run in the biginning of the programC pointer = 0 exitadr = %loc(final) argcount = 1 statadr = %loc(status)  retcode = sys$dclexh(pointer) call lib$establish(final)  return endN****************************************************************************** subroutine xconoff* terminate exit control*9* Call this routine before you exit the program normally.7* otherwise "final" will be called after you call exit**4 integer pointer, exitadr, argcount, statadr, status> common /exithand/ pointer, exitadr, argcount, statadr, status integer sys$canexh, retcode retcode = sys$canexh(pointer) return endN******************************************************************************<* This is where you end up when your program exits. (EitherB* via normal image rundown or because another process called* SYS$FORCEX on it)* subroutine final*? integer*4 mask/'02000000'X/,oldmask ! declare common blockA common /ctrl/ mask,oldmask ! to reset ctrl Y status***4 integer pointer, exitadr, argcount, statadr, status> common /exithand/ pointer, exitadr, argcount, statadr, status** call lib$put_outputA 1 ('Exit Handler here....Enabling CRTL/y and exiting')*J call xconoff ! we can turn off exit controlC Call lib$enable_ctrl(mask,oldmask) ! re-enable CTRL/y trapping by1 ! DCL2 call exit ! and goodbye end#*[DCOLIB.TSLIB_PROGS.PIPE]PIPE.CLD;5+,d./ 4?-`0123KPWO567` *189f1G HJ define verb pipe? image pipe ! EDIT THIS LINE TO REFLECT LOCATION OF PIPE.EXE) parameter p1,value(type=$rest_of_line)$*[DCOLIB.TSLIB_PROGS.PIPE]PIPE.FOR;97+,f:./ 4L-`0123KPWO56`"7@*189f1G HJ Program pipe**@*PIPE a Ultilty to allow unix like filtering and redirection of * Standard input or output.**** Date: 19 April 1985* Author: Andrew W. Potter&* Rochester Institute of Technology* One Lomb Memorial Drive* Rochester, New York 14632*6* Copyright 1987 by Rochester Institute of Technology9* Permission is granted to freely modify and distribute D* (but NOT SELL) this software provided this copyright?* notice is included in all versions distributed.** Installation:*?* 1) Build PIPE. (If you have fortran) Using BUILD_PIPE.COM9* If you dont have fortran just link the supplied objects* as shown in BUILD_PIPE.COM*-* 2) Place PIPE in some utility directory.*B* 3) Pipe can be defined SYSTEM wide by adding the supplied CLD6* to the system DCLTABLES with the following commands.*!* $ INSTALL == "$INSTALL/COMMAND"5* $ SET COMMAND/TABLES=SYS$COMMON:[SYSLIB]DCLTABLES -8* /OUTPUT=SYS$COMMON:[SYSLIB]DCLTABLES pipe)* $ INSTALL REPLACE SYS$LIBRARY:DCLTABLES* * - OR -*1* PIPE may be simply invoked as a foreign command*#* $ PIPE == "$DISK:[DIRECTORY]PIPE"** 4) install PIPE.HLP*1* $ LIBRARY/HELP SYS$HELP:HELPLIB PIPE.HLP***** To use pipe:*4* $ PIPE command1 standard_out** EX:*2* $ pipe show system | search sys$input " COM "*5* Does a SHOW SYSTEM of Computable processes only.*;* $ pipe show system | search sys$input " COM " >COM.DAT* @* Does the same thing but places the output in COM.DAT**8* Look at the help entry for pipe for other examples and"* restrictions on the use of pipe.* implicit integer(a-z) character*80 userstring+ character cmd1*132,cmd2*132,rec*256 include '($jpidef)' character*12 username integer l_u" common /user/ username,l_u integer*4 tt_chan common/channel/ tt_chan+ integer*4 l_username,lenusr,flag/1/ external cancel_ast* integer*2 mypid(2) integer ipid1,ipid2! common /pids/ ipid1,ipid2+ integer*4 mask/'02000000'X/,oldmask2 common /ctrl/ mask,oldmask . character*80 dclcommand,infile,outfile* stat = lib$get_foreign(rec,,l_rec)0 if (.not.stat) call lib$stop(%val(stat)) if (l_rec.lt.1) then rec = ' ' l_rec = 1 endif4 call make_token(rec(1:l_rec),cmd1,l_c1,cmd2,) 1 l_c2,infile,l_if,% 1 outfile,l_of)*H call sys$assign('TT',tt_chan,,) ! assign TTCHAN for terminalF ! AST and NOECHO read QIOs*C Call lib$disable_ctrl(mask,oldmask) ! Tell DCL,"I'll HandleI ! all the CTRL/Ys"*A call xcon_init ! set up exit handler*+ call lib$getjpi(JPI$_MODE,,,mode,,)+ if (mode.eq.JPI$K_INTERACTIVE) thenI Call Enable_Ctrl_C ! enable my ASTs for CTRL/C: Call Enable_Ctrl_y ! and CTRL/Y endifI* Build a unique processname from the first 3 chars of the username)* and the low order part of the pid6 call lib$getjpi(JPI$_USERNAME,,,,username,l_u). call lib$getjpi(JPI$_PID,,,m  DCL_PIPE.BCKf:`$[DCOLIB.TSLIB_PROGS.PIPE]PIPE.FOR;97Lypid(1),,)% username = username(1:3)//'_'/ write (username(5:8),'(z4.4)') mypid(1), call str$trim(username,username,l_u)7 stat = sys$crembx(,ichan,%val(2048),%val(4096),. * %val(0),,username(1:L_U)//'_P')0 if (.not.stat) call lib$stop(%val(stat)) stat = lib$spawnA * (,username(1:l_u)//'_P:',outfile(1:l_of),flag,> * username(1:l_u)//'_I',ipid2,,,cancel_ast)0 if (.not.stat) call lib$stop(%val(stat))**7 call low_write(ichan,'vm = ''f$verify(0)') 9 call low_write(ichan,'on warning then stop/id=0')* call low_write(ichan,cmd2(1:l_c2))& stat = lib$spawn(cmd1(1:l_c1),B * infile(1:l_if),username(1:l_u)//'_P:',flag,A * username(1:l_u)//'_O',ipid1,,,cancel_ast,,, * 'Pipe Subprocess $ ')0 if (.not.stat) call lib$stop(%val(stat)) stat = sys$hiber()0 if (.not.stat) call lib$stop(%val(stat)) end****L* *L* Routines Enable_Ctrl_C and Ctrl_Y are the same but enable separate *L* ASTs for CTRL_y and CTRL_c *L* *****, Subroutine Enable_Ctrl_C**** Implicit Integer (a-z) integer tt_chan common /channel/ tt_chanJ External cancel_ast ! Where to go when ctrl/c is hit Include '($IODEF)' H istat=SYS$QIOW(,%VAL(TT_Chan),%VAL(IO$_SETMODE.OR.IO$M_CTRLCAST)& + ,,,,cancel_ast,,%VAL(3),,,)2 if (.NOT.istat) Call LIB$STOP(%VAL(istat)) Return End*****, Subroutine Enable_Ctrl_Y*** Implicit Integer (a-z) integer tt_chan common/channel/ tt_chanH External cancel_ast ! Where to go when ctrl/y hit Include '($IODEF)'H istat=SYS$QIOW(,%VAL(TT_Chan),%VAL(IO$_SETMODE.OR.IO$M_CTRLYAST)& + ,,,,cancel_ast,,%VAL(3),,,)2 if (.NOT.istat) Call LIB$STOP(%VAL(istat)) Return End*I* *I* These routines is entered automatically when CTRLc or CTRLy is hit *I* **+ Subroutine cancel_ast **********?* This is where control is passed when a user hits Ctrl C* *  implicit integer(a-z) stat = sys$wake(,)0 if (.not.stat) call liB$stop(%val(stat))  return End* subroutine xcon_init external final; integer pointer, exitadr, argcount, statadr, statusE common /exithand/ pointer, exitadr, argcount, statadr, status6c initialize necessary values for exit control5c This is run in the biginning of the programC pointer = 0 exitadr = %loc(final) argcount = 1 statadr = %loc(status) % retcode = sys$dclexh(pointer)! call lib$establish(final)  return end****** subroutine xconoff* terminate exit control*; integer pointer, exitadr, argcount, statadr, statusE common /exithand/ pointer, exitadr, argcount, statadr, status# integer sys$canexh, retcode% retcode = sys$canexh(pointer) return end****** subroutine final*F integer*4 mask/'02000000'X/,oldmask ! declare common blockH common /ctrl/ mask,oldmask ! to reset ctrl Y status***; integer pointer, exitadr, argcount, statadr, statusE common /exithand/ pointer, exitadr, argcount, statadr, status" integer ipid1,ipid2  character*12 username integer l_u" common /user/ username,l_u! common /pids/ ipid1,ipid2*/ call sys$delprc(,username(1:l_u)//'_O')/ call sys$delprc(,username(1:l_u)//'_I')*J call xconoff ! we can turn off exit controlJ Call lib$enable_ctrl(mask,oldmask) ! re-enable CTRL/y trapping by1 ! DCL9 call exit ! and goodbye end) subroutine low_write(ichan,input) implicit integer(a-z) include '($iodef)' integer stat,ichan character*(*) input  character*80 dclcommand dclcommand = input3 call str$trim(dclcommand,dclcommand,l_dcl) ; stat = sys$qio(,%val(ichan),%val(IO$_WRITEVBLK),,,, 1 %ref(dclcommand), 1 %val(l_dcl),,,,)0 if (.not.stat) call lib$stop(%val(stat)) return end**B subroutine make_token(rec,cmd1,l_c1,cmd2,l_c2,infile,l_if, 1 outfile,l_of)* implicit integer(a-z)*2 character*(*) rec,cmd1,cmd2,infile,outfile ( call str$trim(rec,rec,l_rec)  infile = 'NL:' outfile = 'SYS$OUTPUT'  if (l_rec.le.2) then> call lib$put_output('Pipe V1.0 (interactive mode)')# call lib$put_output(' ')3 stat = lib$get_input(cmd1,'CMD1> ',l_c1)3 if (.not.stat) call lib$stop(%VAL(stat))3 stat = lib$get_input(cmd2,'CMD2> ',l_c2)3 if (.not.stat) call lib$stop(%VAL(stat))2 if (l_c2.le.1) stop 'No output Command'; stat = lib$get_input(infile,'Input file> ',l_if)# if (.not.stat) call exit= stat = lib$get_input(outfile,'Output file> ',l_of)# if (.not.stat) call exit0 if (l_of.le.1) outfile = 'SYS$OUTPUT'( IF (l_if.le.1) infile = 'NL:' else5 call locate_file(rec(1:l_rec),'>',outfile)4 call locate_file(rec(1:l_rec),'<',infile)" locbar = index(rec,'|')E if (locbar.eq.0) stop 'pipe: "|" expected in command line'! cmd1 = rec(1:locbar-1) l_c1 = locbar-1 " if (locbar .ge. l_rec) 5 1 stop 'pipe: Command expected after "|"'% cmd2 = rec(locbar+1:l_rec)" l_c2 = l_rec - locbar+1 endif) call str$trim(infile,infile,l_if)+ call str$trim(outfile,outfile,l_of) end- subroutine locate_file(rec,lchr,file) implicit integer(a-z)) character rec*(*),file*(*),lchr*1* locchr = index(rec,lchr) if (locchr.eq.0) return file = ' '( rec(locchr:locchr) = ' ' * loc = locchr lenrec = len(rec) do count = 1,lenrec/ if (rec(count:count).eq.char(12)) then" rec(count:count) = ' ' endif end do& do while (rec(loc:loc).eq.' ')! if (loc.eq.lenrec) thenC call lib$put_output('pipe: Bad redirected file spec.') endif loc = loc + 1 end do ocnt = 1 < do while ((rec(loc:loc).ne.' ').and.(loc.le.lenrec))( file(ocnt:ocnt) = rec(loc:loc) rec(loc:loc) = ' ' ocnt = ocnt + 1 loc = loc + 1 end do return end   DCL_PIPE.BCKf:`$[DCOLIB.TSLIB_PROGS.PIPE]PIPE.FOR;97L*#*[DCOLIB.TSLIB_PROGS.PIPE]PIPE.HLP;6+,g. / 4K -`0123KPWO 56+&07 f*189f1G HJ1 PIPE<PIPE is a RIT developed utility that allows a user to direct<the output of one DCL command directly to the standard input8of another DCL command. This offers users the ability to"do UNIX-like filtering of commands Format:= $ PIPE {Pipe will prompt for commands and files }7 $ PIPE command1 [outfile]2 Command_line_usageBPIPE may have all of its information entered to it on the command Bline. The parameters "command1", "command2" and the "|" character are required. Example 1:( $ MY_ID = F$GETJPI("","USERNAME")< $ PIPE SHOW QUE/BAT/DEV/ALL | SEARCH SYS$INPUT 'MY_ID Example 2:C $ PIPE RUN MY_PROG1 outfile.datC This example runs the program MY_PROG1.EXE with SYS$INPUT comingB from "infile.dat". The standard output of MY_PROG1 is directedD to the input of MY_PROG2.EXE and the output of MY_PROG2.EXE being directed to "outfile.dat". Example 3:K $ PIPE NODESHOW WHAT VAXA,VAXB,VAXC,VAXD | SEARCH SYS$INPUT ABC12342 Inline_usage:PIPE may be invoked by just entering "PIPE" at which point"it will prompt for required input. Example 1: $ PIPE V1.0 (Interactive mode)' CMD1> SHOW QUE/BATCH/DEVICE/ALL1 CMD2> SEARCH SYS$INPUT executing,printing Input file>! Output file> CURRENT.JOBS? This example will search all the BATCH and PRINT queues for@ any currently printing and executing jobs and will store the# result in the file CURRENT.JOBS Example 2:A The same result could be achieved from the following command  procedure: TEST_PIPE.COM $ PIPE! SHOW QUE/BATCH/DEVICE/ALL+ SEARCH SYS$INPUT executing,printing CURRENT.JOBS$ $! end of command procedure.C To achieve the same result as the first example the blank line: must be inserted prior to the filename "CURRENT.JOBS"2 Restrictions$PIPE has the following restrictions.I 1) Since users are restricted to two subprocesses, PIPE may not execute* more than two commands. The sequence:" PIPE cmd1 | cmd2 | cmd3   will NOT work.B 2) For the same reason as above PIPE will not function correctly5 if the user already has any subprocesses active.A 3) PIPE can only process ascii input and output. The output of0 a compiler cannot be directed through PIPE.C 4) PIPE is a command developed here at RIT. While it may prove toB be a helpful utility, users should recognize that it will not+ be available on VMS systems elsewhere.@ 5) Use of PIPE on commands that require interactive input from? the user will produce unpredictable results. Directing the: output of a screen editor through PIPE will not work.2 Hints and SuggestionsDPIPE works by first creating a VMS mailbox device, then SPAWNING two?processes to execute two commands. Since filtering of this typeBworks only when input and output are directed to and from standardAinput and standard output (SYS$INPUT and SYS$OUTPUT on VMS). ManyBVMS utilities expect a filename for input output. These utilitiesAmay often be made to function through PIPE by specifying the name7"SYS$INPUT:" or "SYS$OUTPUT" for the required filename.:Symbol Definitions may make this task easier. For example:% $ grep == "search sys$input:"1 $ pipe where/users/all | grep my_username is the same as:> $ pipe where/users/all | search sys$input: my_usernameESince PIPE is rather expensive in CPU and memory resources, Users areEadvised to use pipe with consideration, especially when the system isloaded."*[DCOLIB.TSLIB_PROGS.PIPE]TEE.COM;2+,i./ 4z-`0123KPWO56\\~7*189f1G HJ$ open/write fi 'p1'$ loop:$ read sys$command rec$ write fi rec$ write sys$output rec $ goto loop $ close fi#*[DCOLIB.TSLIB_PROGS.PIPE]TEST.COM;1+,k./ 4 2-`0123KPWO56 07*189f1G HJ$ pipe whe/us/all sear tt: awpnl:foo.bar