From: HENRY::IN%"carl%CITHEX.CALTECH.EDU%SRI-KL.ARPA%relay.cs.net@rca.com" 3-NOV-1986 23:00 To: info-vax@CitHex.Caltech.Edu Subj: Minimal pipe package for DCL programming The following is a starter kit for those readers of this TC who've always wanted to use pipes with DCL commands but who don't have the DECshell. Any criticisms of the programs offered are welcome, as are any utilities interested readers might write to augment the programs below. Two annoying deficiencies in VMS (in my opinion) are the unwillingness of most DCL commands to paginate their output and the fact that there is no easy way to create a mailbox that will stick around long enough to be useful to somebody programming in DCL. Well, I've finally gotten around to writing a little code to remedy both of these problems, and thought there might be some readers of this TC who'd like a copy of the results. Therefore: The following C program creates a temporary mailbox, then reads a record from it and exits (note: you DO NOT want to run this program other than with the SPAWN/NOWAIT command; otherwise it hangs your process): /*---------------------------------Cut Here-----------------------------------*/ /* USR$SYSTEM:LIFEMBX -- create a mailbox and wait for a write to it */ /* Copyright (C) 1986, The Caltech Odd Hack Committee, no rights reserved */ #include #include #include #include main(nargs, args) int nargs; char **args; { long chan, stat, n; long len[2] = { 82, 410 }; $DESCRIPTOR(devname, "MAILBOX"); char *ptr; if (--nargs > 0) { len[0] = atol(*++args); len[1] = 5 * len[0]; if (--nargs > 0) { ptr = devname.dsc$a_pointer = *++args; devname.dsc$w_length = strlen(*args); for (n = 0; n < devname.dsc$w_length; ++n, ++ptr) if (islower(*ptr)) *ptr = toupper(*ptr); if (--nargs > 0) len[1] = atol(*++args); } } if ((stat = SYS$CREMBX(0, &chan, len[0], len[1], 0, 0, &devname) & 7) != 1) exit(stat); if ((stat = SYS$QIOW(0, chan, IO$_READVBLK, len, 0, 0, 0, 0, 0, 0, 0, 0)) != SS$_NORMAL) exit(stat); if ((len[0] &= 0xFFFF) != SS$_BUFFEROVF) exit(len[0]); } /*---------------------------------Cut Here-----------------------------------*/ Next is a simple DCL procedure to run the above program, assign a (nearly permanent) DCL channel to the mailbox so created, write to the mailbox so the subprocess can die, and put the name of the mailbox in the JOB logical name table (where it will be useful). It uses the old VMS "feature" that if you deassign a logical name created with an OPEN command, the channel still remains open, but you no longer have access to it. This is to keep you from accidentally closing the file and deleting the mailbox, thus ensuring that the mailbox will hang around until the current process dies. $!---------------------------------Cut Here------------------------------------- $! USR$SYSTEM:LIFEMBX.COM -- create a semi-permanent mailbox, with an entry for $! it in the job logical name table $! Copyright (C) 1986, The Caltech Odd Hack Committee, no rights reserved $ if p1 .eqs. "" then write sys$output - "Usage: @lifembx [size] name [size2]" $ if p1 .eqs. "" then exit $ if p2 .eqs. "" then p2 = p1 $ if p2 .eqs. p1 then p1 = 132 $ if p3 .eqs. "" then p3 = p1 $ spawn/nowait/nolog mcr usr$system:lifembx 'p1' 'p2' 'p3' $ wait: wait 0:0:1.0 $ open/read/write/share=write/err=wait tmpfile 'p2': $ write tmpfile "" $ deassign tmpfile $!---------------------------------Cut Here------------------------------------- Finally, the procedure to run DCL commands with pagination, using the above two programs to create a mailbox, running the command with output to the mailbox, and then using the command TYPE/PAGE to display the results $!---------------------------------Cut Here------------------------------------- $! USR$SYSTEM:PAGINATE.COM -- paginate the output of a DCL command $! Copyright (C) 1986, The Caltech Odd Hack Committee, no rights reserved $ if f$trnlnm("PAGEPIPE") .eqs. "" then - $ @USR$SYSTEM:lifembx 132 pagepipe 132 $ if p1 .eqs. "" then exit $ cmd = p1+" "+p2+" "+p3+" "+p4+" "+p5+" "+p6+" "+p7+" "+p8 $ cmd = f$edit(cmd, "TRIM") $ spawn/nowait/output=pagepipe:/input=nl:/nolog/proc=paginate cmd $ type := type/pag $ type pagepipe: $ set noon $ msg = f$env("MESSAGE") $ set message/noid/nosev/nofac/notext $ stop paginate $ set message'msg' $ loop: open/read tmpfile pagepipe: $ read/time=0/end=done/err=done tmpfile fubar $ goto loop $ done: close tmpfile $!---------------------------------Cut Here------------------------------------- The executable from the C program and both procedures should be kept in the directory USR$SYSTEM. To avoid having somebody tell me "Yes, that's all very nice, but you could just redirect output from the command to a disk file, then type the result", I should point out that these programs don't require that the command complete before you look at the output, so if you decide from early output that you want to abort the command, doing it this way can save considerable time. The first two programs also, of course, open the way for a DCL equivalent to pipes; hence the naming of the mailbox in the third program.