Search

Saturday, July 18, 2020

OpenVMS: Purge/Delete Expired Licenses and Clean Up LMF DB License Database

Supratim Sanyal's Blog: OpenVMS VAX License PAK


This is a thread from the comp.os.vms newsgroup. The archived conversation is at:


---

comp.os.vms ›
LICENSE PURGE ?
7 posts by 6 authors 

Peter LANGSTOEGER
3/14/01
Since the VMS hobbyist program is there (many thanks for that !!), I have
a bunch of licenses loaded which starts to terminate now. And I start to
feel tired of deleting yet another expired license...
Is there a LMF command to delete all expired licenses at once ?

--
Peter "EPLAN" LANGSTOEGER           Tel.    +43 1 81111-2651
Network and OpenVMS system manager  Fax.    +43 1 81111-888
<<< KAPSCH AG  Wagenseilgasse 1     E-mail  ep...@kapsch.net
A-1121 VIENNA  AUSTRIA              "I'm not a pessimist, I'm a realist"

Click here to Reply

Martin Vorlaender
3/14/01
Peter LANGSTOEGER (ep...@kapsch.net) wrote:
> Since the VMS hobbyist program is there (many thanks for that !!), I have
> a bunch of licenses loaded which starts to terminate now. And I start to
> feel tired of deleting yet another expired license...
>
> Is there a LMF command to delete all expired licenses at once ?
I solved (or circumvented) that problem by issuing a $ LICENSE CREATE
before executing the command procedures that register the new hobbyist
licenses. But then, the hobbyist licenses are the only ones on my system.

I guess one could write a quick perl script to look over OPERATOR.LOG
and issue appropriate $ LICENSE DELETE commands.

cu,
  Martin
--
One OS to rule them all       | Martin Vorlaender  |  VMS & WNT programmer
One OS to find them           | work: m...@pdv-systeme.de
One OS to bring them all      |   http://www.pdv-systeme.de/users/martinv/
And in the Darkness bind them.| home: mar...@radiogaga.harz.de


Hunter Goatley
3/14/01
On 15 Mar 2001 00:45:53 +0100, ep...@kapsch.net (Peter LANGSTOEGER) wrote:
>Since the VMS hobbyist program is there (many thanks for that !!), I have
>a bunch of licenses loaded which starts to terminate now. And I start to
>feel tired of deleting yet another expired license...
>
>Is there a LMF command to delete all expired licenses at once ?
>
$ delete sys$system:lmf$license.ldb;*
A bit drastic, but it works.

$ LICENSE DELETE *

also works, but, again, is a bit drastic.  Less drastic, and one
that will probably do exactly what you want (delete the hobbyist
licenses and leave any other intact):

$ LICENSE DELETE */AUTHORIZATION=DECUS-USA-*

or whatever common authorization string they have.

Or:

$ LICENSE DISABLE */AUTHOR=DECUS-USA-*
$ LICENSE DELETE */STATUS=DISABLED

Hunter
------
Hunter Goatley, Process Software, http://www.process.com/
goath...@goatley.com     http://www.goatley.com/hunter/


Robert Deininger
3/15/01
In article <3ab0...@news.kapsch.co.at>, ep...@kapsch.net wrote:
> Since the VMS hobbyist program is there (many thanks for that !!), I have
> a bunch of licenses loaded which starts to terminate now. And I start to
> feel tired of deleting yet another expired license...
>
> Is there a LMF command to delete all expired licenses at once ?
There's a LICENSE DELETE/STATUS=DISABLED
There's a LICENSE LIST/BEFORE/TERMINATION
Alas, there's no LICENSE DELETE/BEFORE/TERMINATION

I've made a command file that parses the output of
   LICENSE LIST/FULL/BEFORE/TERM,
generates a bunch of LICENSE DISABLE commands, and does
   LICENSE DELETE/STATUS=DISABLED.

This will get rid of terminated licenses and leave the others intact.

I can email or post the command file if there's interest.

--
Robert Deininger
rdein...@mindspring.com


Robert Deininger
3/15/01
In article
<rdeininger-15...@user-2ivec5u.dialup.mindspring.com>,
rdein...@mindspring.com (Robert Deininger) wrote:

> I can email or post the command file if there's interest.

I've gotten a couple of requests, so I'll just post the following
use-at-your-own-risk DCL.

There are two files below.

JRDDCL.COM is pretty much stolen from Hoff's book; I've only typed in what
I've needed so far, so it isn't the whole library.  The main utility
depends on these routines.  You'll have to decide where to keep the
library on your system. The second routine defines a symbol to locate the
library; you'll want to adjust that definition.  You can also change all
occurances of "jrd" to your own initials if you want.

DISABLE_TERMINATED_LICENSES.COM is the utility that disables all the
terminated license PAKs.  It leave the LICENSE DELETE for you to do by
hand.  Since I'm parsing text output from LICENSE LIST, it may go wrong if
the format changes, or if you have PAKs that don't follow the pattern I
expect.  I STRONGLY suggest you accept the default options to make a copy
of the license file before changing it, and to view the generated command
file before it runs.  This has been tested on CSLG licences.  It's
supposed to work with hobbyist PAKs as well, but I haven't tested since
mine haven't expired yet.

This would be moot if the LICENSE folks would add the qualifiers that LIST
knows to other commands like DISABLE and DELETE.

Here's the stuff.  You may have to de-wrap a few lines.


JRDDCL.COM:

$!   DCL subroutine library
$!      Modelled after the example in "Writing Real Programs in DCL, 2nd
$!      Edition."
$
$  jrddcl__status = %x10000000
$  jrddcl__success = jrddcl__status + %x0001
$  on control_y then exit jrddcl__status + %x0004
$  on warning then exit $status .or. %x10000000
$
$  display = "write sys$output"
$  goto 'p1'
$
$! Title:   Ask a Question
$
$! Synopsis:   This subroutine asks the user a question and returns
$!    the answer.  The prompt for the question is composed
$!    of a query string and optionally a default answer.
$
$! Parameters: P2: A global symbol to receive the answer.
$!    P3: The data type of the answer.  B for boolean
$!        (yes,no); I for integer; S for string.
$!    P4: The query string for the question.  It must end
$!        with a punctuation character and no space.
$!    P5: The default answer (optional; if not specified
$!        then an answer must be entered).
$!    P6: A comma-separated list of options:
$!       H: Display help before asking question.
$!       S: Skip a line before asking question.
$!       U: Upcase the input string.
$!       Z: Allow Ctrl/Z as an nswer.
$!    P7: The help specifier (optional).  It must be in
$!        in the form "procedure [parameter...]".  The
$!        procedure is invoked with the @-sign command.
$
$ASK:
$
$  signal = "@" + f$environment("PROCEDURE") + " signal ask"
$  if p3 .eqs. "B" .and. p5 .nes. "" .and. f$type(p5) .eqs. "INTEGER"
$       then
$     p5 = f$element(p5,"/","NO/YES")
$  endif
$  if p5 .nes. ""
$  then
$     p4 = f$extract(0,f$len(p4)-1,p4) + -
           " [" + p5 + "]" + f$extract(f$len(p4)-1,1,p4)
$  endif
$  if f$locate("S",p6) .ne. f$length(p6) then display ""
$  if f$locate("H",p6) .ne. f$length(p6) then @'p7'
$
$a10: read sys$command/prompt="''p4' " input/end_of_file=a_eof
$  if input .eqs. "" then input = p5
$  input = f$edit(input,"TRIM")  
$  if input .eqs. ""
$  then
$     signal w inputreq "Please enter a value; there is no default."
$  else if input .eqs. "?"
$  then
$     if p7 .nes. "" then @'p7'
$     if p7 .eqs. "" then display "There is no help for this question."
$  else
$     goto a_'p3'
$a_B:    input = f$edit(input,"UPCASE")
$     if f$locate(input,"YES") .eq. 0 .or. -
         f$locate(input,"NO") .eq. 0
$     then
$        input = input .and. 1
$        goto a19
$     else
$        signal w yesnoreq "Please answer YES or NO."
$     endif
$     goto a15
$
$a_I:    if f$type(input) .eqs. "INTEGER"
$     then
$        input = f$integer(input)
$        goto a19
$     else
$        signal w intreq "The input must be an integer."
$     endif
$     goto a15
$
$a_S:    if f$locate("U",p6) .ne. f$length(p6)
$     then
$        input = f$edit(input,"UPCASE")
$     endif
$     goto a19
$a15:
$  endif
$  endif
$  goto a10
$a_eof:
$  input = "^Z"
$  if f$locate("Z",p6) .ne. f$length(p6) then goto a19
$  signal i invctrlz "End-of-file is not a valid response."
$  goto a10
$a19:
$  'p2' == input
$  exit jrddcl__success
$
$! Title:   Signal an Informational or Error Message
$
$! Synopsis:   This subroutine "signals" a message, producing one
$!    or more message lines in the standard OpenVMS format.
$!    It also exits with a status whose severity matches
$!    that of the message.
$
$! Parameters: P2: The message facitlity code.
$!    P3: The message serverity (S, I, W, E, or F).
$!    P4: The message identification.
$!    P5: The message text.
$!    Pn: Optional message lines or status codes whose
$!        corresponding message lines are to me included.
$
$! Status:  The severity of the exit status is equal to the
$!    message severity, except in the case of warnings.
$!    If the message severity is W, and informational
$!    severity is included in the status so that the
$!    caller's error handler is not invoked.
$
$SIGNAL:
$
$  prefix = f$fao("%!AS-!AS-!AS, ",p2,p3,p4)
$  i = 4
$s10:    i = i + 1
$     if i .gt. 8 then goto s19
$     if p'i' .eqs. "" then goto s19
$     text = p'i'
$     if f$type(text) .eqs. "INTEGER"
$     then
$        text = f$message(text)
$     endif
$     if f$ext(0,1,text) .nes. "%" then text = prefix + text
$     if i .gt. 5 then text [0,1] := "-"
$     display text
$     goto s10
$s19:
$  if p3 .eqs. "W" then p3 = "I"
$  exit jrddcl__status + f$locate(p3,"WSEIF")
$


DISABLE_TERMINATED_LICENSES.COM:

$! Title:   Disable Terminated Licenses
$
$! Synopsis:   This command file disables all the terminated licenses
$!    in the active license database, which is defined by
$!    the current value of LMF$LICENSE.
$
$! Parameters: None
$
$! Author:  Robert Deininger
$! Created: January, 2001
$
$
$! Define some simple status codes.
$
$ lic__status  = %x10000000
$ lic__success = lic__status + %x0001
$ lic__ctrly   = lic__status + %x000C
$
$! Set up interrupt and error handlers.
$
$ status = lic__success
$ on control_y then goto control_y
$ on warning then goto error
$
$! Define some useful symbols.
$ say = "write sys$output"
$ jrdcall = "@jrddcl.com"     !!! <<<---- adjust this as needed
$
$! The real work starts here.
$
$ tempfile1 = "terminated.lis;"
$ tempfile2 = "disable_terminated.com;"
$
$ current_ldb = f$search(f$trnlnm("lmf$license"))
$
$ type sys$input

 Utility to DISABLE all the terminated licenses in the active
 license database...

 The active database is:
$ say "   ",current_ldb
$ type sys$input

 This utility makes many changes to the license database.  Do you
 want a backup copy of the database file saved before changes
 are made?
$10:
$ on warning then goto 10
$ jrdcall ask lic__answer b "Save a backup copy?" "YES" U,S
$ on warning then goto error
$
$ if lic__answer
$ then
$    current_ldb = current_ldb - f$parse(current_ldb,,,"version")
$    say ""
$    copy/log 'current_ldb' 'current_ldb'
$    current_ldb = f$search(f$trnlnm("lmf$license"))
$    say ""
$    say " The new highest version will be modified."
$ endif
$
$ say " Finding terminated licenses..."
$
$! Get a list of terminated licenses.
$ license list/before/terminated/full/output='tempfile1'
$
$ say " Making a command file to disable licenses..."
$
$! Open the input and output files.
$ open/read  tempfile1 'tempfile1'
$ open/write tempfile2 'tempfile2'
$
$ target_string = "-----------------------"
$main_loop:
$ gosub find_string
$ if input_string .nes. ""
$ then
$!   We have read the "header" line for a single license.
$!   Look for expected beginnings on the next 4 lines, and save the good
$!   parts.
$
$    get_string = "Issuer:"
$    gosub get_string
$    if result_string .nes. ""
$    then
$       issuer = result_string
$    else
$       goto main_loop
$    endif
$
$    get_string = "Authorization:"
$    gosub get_string
$    if result_string .nes. ""
$    then
$       authorization = result_string
$    else
$       goto main_loop
$    endif
$
$    get_string = "Product Name:"
$    gosub get_string
$    if result_string .nes. ""
$    then
$       product_name = result_string
$    else
$       goto main_loop
$    endif
$
$    get_string = "Producer:"
$    gosub get_string
$    if result_string .nes. ""
$    then
$       producer = result_string
$    else
$       goto main_loop
$    endif
$
$    ! We have the 4 important pieces of information we wanted.  Generate
$    ! a LICENSE DISABLE command.
$    gosub write_command
$
$    goto main_loop
$ endif
$
$! We have processed the whole input file.
$ close tempfile1
$ write tempfile2 "$ exit"
$ close tempfile2
$
$20:
$ on warning then goto 20
$ jrdcall ask lic__answer b "Do you want to view the command file?" -
             "YES" U,S
$ on warning then goto error
$
$ if lic__answer
$ then
$    type/page 'tempfile2'
$ endif
$
$30:
$ on warning then goto 30
$ jrdcall ask lic__answer b -
     "Do you want to exectute these commands to modify the license database?" -
     "" U,S
$ on warning then goto error
$
$ if lic__answer
$ then
$    @'tempfile2'
     type sys$input

 Disabling is complete.

 You may want to execute
   $ LICENSE DELETE */STATUS=DISABLED/LOG
 to completely remove all disabled licenses from the database.
$
$ else
$    say ""
$    say " Modifications cancelled."
$ endif
$
$ goto cleanup
$
$CONTROL_Y:
$ status = lic__ctrly
$ goto cleanup
$
$ERROR:
$ status = $status
$ goto cleanup
$
$CLEANUP:
$ if f$search(tempfile1) .nes. "" then delete/nolog/noconfirm 'tempfile1'*
$ if f$search(tempfile2) .nes. "" then delete/nolog/noconfirm 'tempfile2'*
$
$ if f$type(lic__answer) .nes. "" then delete/symbol/global/nolog lic__answer
$
$ exit status .or. %x10000000
$
$FIND_STRING:
$! This subroutine reads lines from tempfile1 until it obtains a line that
$! begins with target_string.  It returns with input_string equal to the
$! entire input line, or the null string if the end of the file was reached
$! without finding the target.
$
$find_loop:
$ read/end_of_file=end_of_file tempfile1 input_string
$ if f$locate(target_string,input_string) .eq. 0
$ then
$    ! The current string begins with the target.
$    return ! (FIND_STRING)
$ else
$    goto find_loop
$ endif
$
$end_of_file:
$ input_string = ""
$ return ! (FIND_STRING)
$
$GET_STRING:
$! This subroutine reads a line from tempfile1, checks that it starts
$! with get_string, and returns in result_string the last part of the string.
$! The "last part" is the second element delimited by " ", after the part
$! matching get_string is removed.
$
$ read tempfile1 input_string
$ if f$locate(get_string,input_string) .eq. 0
$ then
$    ! The current string begins with the target.
$    temp = f$edit((input_string - get_string),"compress")
$    result_string = f$element(1," ",temp)
$
$ else
$    say "Unexpected line.  Expected ''get_string', found:"
$    say line
$    say ""
$
$    result_string = ""
$ endif
$
$ return ! (GET_STRING)
$
$WRITE_COMMAND:
$! This subroutine writes a single "license disable" command to tempfile2,
$! using the information in symbols PRODUCT_NAME, AUTHORIZATION, ISSUER,
$! and PRODUCER.
$
$ write tempfile2 "$ license disable/log ''product_name' -"
$ write tempfile2 "    /authorization=''authorization' -"
$ write tempfile2 "    /issuer=''issuer' -"
$ write tempfile2 "    /producer=''producer'"
$ write tempfile2 "$"
$
$ return ! (WRITE_COMMAND)


Jim Agnew
3/20/01
I followed Mr. Robert Deininger's
kindly given com files, and when I tried to do the license delete/disabled * step, (or however it's spelled), lmf whined about being
greater than a 64K command..  I had about oh, 3,000 old licenses clogging up my db.  we simply edited the disable_licenses.com file
into a delete_licenses.com, and nuked them.

my license db did NOT shrink...  should I copy them over to a new file to reduce the file size, or just leave it.  

many thanks, my console is no longer incessantly beeping...

j.

- show quoted text -

Hoff Hoffman
3/20/01
In article <3AB7C29...@hsc.vcu.edu>, Jim Agnew <ag...@hsc.vcu.edu> writes:
:my license db did NOT shrink...  should I copy them over to a new file to
:reduce the file size, or just leave it.  
  The RMS indexed file storage allocation does not normally shrink without
  outside assistance.

  Having a larger-than-required indexed file containing deleted records
  is not (usually) of any particular consequence.  (Salient exceptions:
  severely oversized files when disk space is correspondingly severely
  constrained, large numbers of deleted records and other cruft built up
  within an indexed file when frequently accessed, etc.)

  You would need to CONVERT/RECLAIM or similar conversion, and not COPY,
  to remove the deleted records and to reorganize the internal structures
  of an RMS indexed file.

 ---------------------------- #include <rtfaq.h> -----------------------------
      For additional, please see the OpenVMS FAQ -- www.openvms.compaq.com    
 --------------------------- pure personal opinion ---------------------------
   Hoff (Stephen) Hoffman   OpenVMS Engineering   hoffman#xdelta.zko.dec.com

Recommended Products from Amazon