Operating System - OpenVMS
1748080 Members
5254 Online
108758 Solutions
New Discussion

Re: Tool to change INQUIRE statements to READ in command procedures?

 
SOLVED
Go to solution
David R. Lennon
Valued Contributor

Tool to change INQUIRE statements to READ in command procedures?

Hi,

   Does anyone know of or have (that they can share) a tool that can be run on a DCL command procedure file and "edit" it such that all INQUIRE statements are changed to code using READ/PROMPT that provides the functional equivalent??

  I worked at a site several decades(!) ago that had a DEC consultant on-site that wrote this in the VAX SCAN language and it worked quite well but I didn't have the opportunity to grab the source code, the company is out of business and I don't think he submitted the code to DECUS, etc.

  The problem I am trying to solve is that we have several hundred DCL command procedures with the INQUIRE command in them that regular users run and we want to convert these users to be CAPTIVE, where INQUIRE is not allowed to be run.

  The code to do this turned out to be a it more complex that it would appear, as I recall, such as; the order of the parameters for these two commands are reversed, the line of code may span multiple lines of text, /NOPUNCTUATION qualifier had to be dealt with, INQUIRE would upcase and trim responses and so on.

  I am aware there is a ASK program that may be better than INQUIRE or READ but I would like to stick with vanilla DCL as much as possible.

 

Thanks,

Dave

10 REPLIES 10
Bill Hall
Honored Contributor

Re: Tool to change INQUIRE statements to READ in command procedures?

Dave,

 

Freeware v6 volume 1 contains a utility called FIND.  The simple description is "SEARCH with Replacement Capabilities".  IIRC, this gem came from VMS engineering, and it installs as a DCL verb from a PCSI kit for VAX, Alpha and IA64.  It supports enhanced VMS style wildcards and regular expressions.

 

 

Bill Hall
Hein van den Heuvel
Honored Contributor

Re: Tool to change INQUIRE statements to READ in command procedures?

Seemed like a fun challenge before going to bed...

I opted for PERL and made it handle a bunch of test cases.

It just deals with one file at a time, but I'm sure you can find a way to make it process a series of files.

I'm also sure your scripts will find ways to break it, but give it a go?

Let me know how it goes!

 

Usage :   $ PERL INQ.PL input_with_inquiry.COM > output_with_read.COM

 

Perl script...

 

use strict;
use warnings;
#
# Working assumptions:
#  - Working INQ code
#  - No sillyness like empty continued line
#  - Switches with command ... may work anywhere... untested.
#  - Global symbols alerted, solved with simple re-assign.
#  - no continuation line comments

my ($inquires, $make_global_attempt);

while (<>) {
   if ( s/(^\s*\$\s*(\w+:)?\s*)IN(QU?\w*)([ \t\/\-].*)/$1~INQUIRE~$4/i ) { # looks like work to do?
       $inquires++;   # count it for final report, and helper labels.
       my ($global, $nopunc, $comment) = (0,0,'');
       $_  .= <> while s/\s*-\s*$/ /;   # Add on the next line if this line ended with dash and spaces
       s/\n//g;                         # strip new-lines
       $global = s%\s*/gl[^/ \t]+%%i;   # set global flag if word removed from string.
       $nopunc = s%\s*/nopu[^/ \t]+%%i; # set nopunc flag if word removed from string.
       s%\s*/lo[^/ \t]+%%i;             # strip meaningless /LOCAL
       s%\s*/pu[^/ \t]+%%i;             # strip meaningless /PUNC
       if (/(.*?(".*")?)\s*(!.*)$/) {   # stash aways COMMENT
           $comment = ' ' . $3;
           $_ = $1;
       }
       $_ .= '"' if /^[^"]+"[^"]+$/;      # add missing closing double-quote
       $_ .= ' "' . uc($1) . '"' if /~INQUIRE~\s+(\S+)\s*$/; # Just a symbol, no prompt string?
       s/"\s*$/: "/ unless $nopunc;       # add punctuation
       m /^(.*?)~INQUIRE~\s+(\S+)\s+(".*)$/; #  (re)match string componets for final shuffle.
       $_ = "$1 READ/END=inq_${inquires}/PROMPT=$3 SYS\$COMMAND $2$comment\n\$inq_${inquires}:\n";
       if ($global) {
           printf STDERR "!WARNING Source line $. requested GLOBAL for <$2>. Might not work.\n";
           $make_global_attempt = "\$ $2 == $2 !WARNING Source line $. requested GLOBAL for <$2>.\n";
       }

   }
   print;  
   if ($make_global_attempt) {
       print $make_global_attempt;
       $make_global_attempt = "";
   }
}
printf STDERR "%s DCL INQUIRE statements found\n", $inquires ? $inquires : 'NO';

 

torture test...

 

$if p1.nes."" then goto 'p1
$inq x_01 "basic"
$y="02"
$inq x_'y' "complex symbol"
$inq x_03 -
 "test with prompt on second line"
$inq -
 x_04 "test with symbol and prompt on second line"
$ -
inq x_05 "test with everything as continuation"
$!inq x_bad "inq in comment"
$  inq  x_06 "leading spaces an comment" ! hello
   $  inq  x_07 "more leading spaces and comment" ! hello inquire
      $ inq x_08 "more leading spaces and quoted string in comment " ! "inquire"
$label: inquire x_09 "label on line"
$inquire/nopun -
  x_10 -
  "test over three line, nopunc"
$ inqublahbla x_11 "test with 4 character rule"
$write sys$output "just the word inquire in a string" ! inquire
$ inquest x_12
$ inq x_13 ! No prompt, but comment present
$ inq/glo x_14 "not a local symbol.
$show symb x_*
$exit

 Enjoy!

Hein

 

 

 

B Claremont
Frequent Advisor

Re: Tool to change INQUIRE statements to READ in command procedures?

Here's an option using DCL and good old EDT.

 

$!**********
$! EDIT.COM
$!    This procedure provides an example of how to use the
$!    EDT editor in line mode to carry out mass edits of
$!    a specific file type.
$!
$    EDIT := EDIT /EDT
$!
$ LOOP:
$    FILE = F$SEARCH("*.COM;")
$    IF FILE .EQS. "" THEN GOTO END
$    IF F$PARSE(FILE,,, "NAME") .EQS. "EDIT" THEN GOTO LOOP
$!
$    EDIT 'FILE'
SUB\GEN$UTILITIES\SYS$UTILITIES\WHOLE
EXIT
$!
$    GOTO LOOP
$!
$ END:
$    EXIT
$!
$!**************************************************************************
$!*                   DISCLAIMER                         *
$!*    This software is provided as a service by Migration Specialties       *
$!*    International (MSI).  This software is provided as is and is        *
$!*    neither supported nor warrantied by MSI.  The customer may use       *
$!*    and modify this software at their own risk.                    *
$!*            Migration Specialties International           *
$!*            www.MigrationSpecialties.com                 *
$!*            No warranties either expressed or implied.        *
$!**************************************************************************

www.MigrationSpecialties.com
John Gillings
Honored Contributor

Re: Tool to change INQUIRE statements to READ in command procedures?

Dave,

 

   I think the lower risk path is to write yourself a replacement image for the INQUIRE command, using the DCL CLD facilities. That way all the potential complications to do with parameters, qualifiers, comments, continuation lines are dealt with for you by DCL. It's not a difficult command,

 

  One issue you may need to worry about. My program, and Hein's edits will both change the behaviour of the input. INQUIRE will UPPERCASE the input, unless quoted (and will remove outer quotes).

 

  With your own image you can decide if you want to mimic the true INQUIRE behaviour or ignore the issue and assume it won't be a problem. (Of course, INQUIRE will also substitute symbols and execute lexical functions, but that's the behaviour you're trying to eliminate in going to captive users).

 

I've built a MACRO32 prototype which passes Hein's test. Let me know if you're interested and I'll package it into a transportable form (you won't be able to compile this directly, it's dependent on my macro libraries). Since you've said you don't want to go that path, I haven't put in the work.

 

 

        .TITLE INQUIRE
;
; See documentation in INQUIRE_CLD.CLD
;
        .LIBRARY "UTIL"
        StandardPsects
$CLIMSGDEF
CLI_NO_SIGNAL
$SSDEF
$STSDEF
$DSCDEF
$EFNDEF
$IODEF
StringUtils
SelfStr P1
SelfStr P2
SelfStr SYS$COMMAND
ConstStr Punct <: >
        .PSECT data
StrSize=256
String SymName,StrSize
String SymVal ,StrSize
String Prompt ,StrSize
String Scratch,StrSize
qiosb:
 iostat: .WORD
 iochars:.WORD
 ioterm: .WORD
 iotrmsz:.WORD
CliTable:    .LONG LIB$K_CLI_LOCAL_SYM
commchan: .WORD 0

   ; Program uses CLD to parse the command from a foreign string

        ForeignCLD_Main INQUIRE
        .PSECT code
        .ENTRY DoInquire,^M<R2,R3,R4,R5,R6,R7,R8,R9,R10,R11>
;
;  Main routine.
           Qualifier     GLOBAL
           Qualifier     LOCAL
           Qualifier     PUNCTUATION
           IF_FLAG GLOBAL <MOVL #LIB$K_CLI_GLOBAL_SYM,CliTable>

           CLI_GET_STRING P1,SymName
           BLBC R0,Bad
           CLI_GET_STRING P2,Prompt
           IfLBC R0 <CopyStr SymName Prompt>
           BLBC FlagPUNCTUATION, GotPrompt
             Concat Scratch Prompt Punct
             CopyStr Scratch Prompt
             INCW Prompt_w_len
           GotPrompt:
           $ASSIGN_S devnam=SYS$COMMAND chan=commchan
           BLBC R0,Bad
          $QIOW_S efn=#EFN$C_ENF, chan=commchan, func=#IO$_READPROMPT, iosb=qiosb -
                                  p1=SymVal_t_buf p2=SymVal_w_len -
                                  p5=Prompt_a_buf p6=Prompt_w_len
          BLBC   R0,Bad
          MOVZWL iostat,R0
          BLBC   R0,Bad
          MOVW iochars,SymVal_w_len
          upcase SymVal
          unquote SymVal
           CALL LIB$SET_SYMBOL SymName SymVal CliTable
         Bad: RET
        .END Start

 

A crucible of informative mistakes
John Gillings
Honored Contributor

Re: Tool to change INQUIRE statements to READ in command procedures?

Sorry, Forgot to include the CLD

 

MODULE INQUIRE_CLD
DEFINE VERB INQUIRE
ROUTINE DOINQUIRE
!
! Duplicate INQUIRE command for use in captive procedures
!
!   See DCL HELP
!
!
PARAMETER P1, VALUE(REQUIRED)
!
!  Condition value to signal
!  Parameter may also be an FAO control string
!
PARAMETER P2, VALUE
qualifier       global,nonnegatable
qualifier       local,nonnegatable
qualifier       punctuation,default

 

A crucible of informative mistakes
Hein van den Heuvel
Honored Contributor
Solution

Re: Tool to change INQUIRE statements to READ in command procedures?

 

 

Nice work John!

Of course the systems would now have to shlepp this  image/cld file around.

 

Thanks for reminding me about INQ upcasing inputs.

 

The attached revision of the perl script I posted addresses that by using a temp variable to read into

and then it uses an assignment with := or :== to set up the requested symbol.

 

Of course that re-introduces the security vulnerabilty with symbol substituion for which INQUIRE was banned in the first place. So realistically one may have to use F$EDIT(x,"UPCASE") but then you have to parse away or honor the double quotes manually.

 

Cheers,

Hein.

 

 

 

B Claremont
Frequent Advisor

Re: Tool to change INQUIRE statements to READ in command procedures?

I've always liked this instead of INQUIRE:

 

$ ASK :== READ SYS$COMMAND /END_OF_FILE=CANCEL_PROCEDURE /PROMPT="

 

$ ASK "File Name> " FILE

 

More examples can be found here: http://www.migrationspecialties.com/pdf/VTJ_F$GETQUI.pdf

www.MigrationSpecialties.com
David R. Lennon
Valued Contributor

Re: Tool to change INQUIRE statements to READ in command procedures?

Thanks to all for the input.

 

Personal choice, but I don't want to pursue coming up with a "fake" private version of the INQUIRE DCL command verb, but nice to know it can be done.

 

The Perl code from Hein is pretty much exactly what I am looking for, much thanks! I'll be able to run with that, I just have to learn some perl. I would want to use the lexical functions and not let DCL do the symol upcasing. I wouldn't want to re-open the security hole which is the reason the VMS developers prohibited INQUIRE with captive usernames.

H.Becker
Honored Contributor

Re: Tool to change INQUIRE statements to READ in command procedures?

Even if the perl script does what you need, I would still override the original inquire command with an own CLD. You don't need to implement an inquire command but you may want to trap all the cases where Hein's script doesn't correctly replace the old inquire command, for example

 

 

$ ./inq.pl             

$ if f$mode() .eqs. "INTERACTIVE" then $ inq/glo x_15 "inter"
$ if f$mode() .eqs. "INTERACTIVE" then $ inq/glo x_15 "inter"
$ ask:=inquire/nopunc
$ ask:=inquire/nopunc
$ ask file "Filename "
$ ask file "Filename "