[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference vaxaxp::vmsnotes

Title:VAX and Alpha VMS
Notice:This is a new VMSnotes, please read note 2.1
Moderator:VAXAXP::BERNARDO
Created:Thu Jan 23 1997
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:703
Total number of notes:3722

207.0. "SYS$LOOKUP_LICENSE finds PAK that $LICENSE LIST doesn't..." by GALVIA::DUKE (Ronan) Tue Feb 18 1997 09:32

Since the Software_licensing notesfiles looks very quiet, I'm cross-posting this 
question here.   I'll delete it if there's a better place to put it...

thanks,
Ronan

        <<< YUPPIE::$1$DIA1:[NOTES$LIBRARY]SOFTWARE_LICENSING.NOTE;54 >>>
                         -< Software Licensing Issues >-
================================================================================
Note 437.0 SYS$LOOKUP_LICENSE finds PAK that $LICENSE LIST doesn't... No replies
GALVIA::DUKE "Ronan"                                145 lines  18-FEB-1997 06:28
--------------------------------------------------------------------------------
Hi,
  A customer of ours is having a problem which seems to be related to the
licenses that are/aren't on their system.   The product checks for the CDA-RT
license and if it doesn't find it it then looks for DW-MOTIF.
  I did a $ LICENSE LIST on my own system and found CDA-RT but no DW-MOTIF.  As
expected, my product worked.   I then deleted the CDA-RT license from the
system and my product continued to work !   I then took the license check code
out of the product source code and created a little test program to check 
whether it would find any of the following licenses on the system:
  CDA-RT
  DW-MOTIF
  Foo
 When I run this on my own system (VAX/VMS V6.1), it finds both CDA-RT and
DW-MOTIF even though neither show up when I do a $LICENSE LIST.
 Thinking that maybe there was some caching going on, I rebooted a test system
(VAX/VMS V7.1) and ran my test program.  Again, it finds the CDA-RT and
DW-MOTIF PAKs even though neither show up on a $ LICENSE LIST.
  Thankfully, in both cases, the PAK for the product Foo is not found.
 Anyone out there can point out the error of my ways (gently :-)  ?
 thanks in advance,
-ronan

----------check_license.c----------------------

/*
**  Include Files
*/
#include <lmfdef.h>
#include <stdio.h>
#include <descrip.h>
#include <stdlib.h>
/*
**  Type Definitions
*/
struct lmf_item {
    short int	 length;
    short int    code;
    void	*address;
    long	*ret_length;
};


/*
**  Static Data Definitions
*/

static char CdaRT_prod_name_str[] = "CDA-RT";
static char DWMotif_prod_name_str[] = "DW-MOTIF";
static char CdaRT_producer_str[] = "DEC";
static char Foo_prod_name_str[] = "Foo";
static short int CdaRT_prod_ver[2] = {1,0};
static short int DWMotif_prod_ver[2] = {0,0};
static char CdaRT_prod_datename_str[] = "28-JAN-1992 0:0:0.0";
static char DWMotif_prod_datename_str[] = "28-JAN-1992 0:0:0.0";


extern unsigned long sys$bintim
    (const struct dsc$descriptor_s *, const void *);

extern unsigned long sys$lookup_license
    (const struct dsc$descriptor_s *, const struct lmf_item *,
     const struct dsc$descriptor_s *, const long *, void *, unsigned long);

extern unsigned long sys$release_license (void *);



main (argc, argv)
int argc;
char *argv[];
    {

    unsigned int    status;
    unsigned long   license_context[4];
    int		    per_user_license;
    long int	    prod_date[2];
    struct lmf_item itm_lst[3];
    long	    flags = LMF$M_RETURN_FAILURES; /* | LMF$M_BROADCAST_FAILURES
*/


#pragma nostandard

    $DESCRIPTOR (CdaRT_prod_name, CdaRT_prod_name_str);
    $DESCRIPTOR (DWMotif_prod_name, DWMotif_prod_name_str);
    $DESCRIPTOR (Foo_prod_name, Foo_prod_name_str);
    $DESCRIPTOR (CdaRT_prod_datename, CdaRT_prod_datename_str);
    $DESCRIPTOR (DWMotif_prod_datename, DWMotif_prod_datename_str);
    $DESCRIPTOR (CdaRT_producer, CdaRT_producer_str);
#pragma standard


    /* Transform the time into binary and set up the item list */
    status = sys$bintim(&CdaRT_prod_datename, prod_date);
    if (!(status & 1))
       exit (-1);

    itm_lst[0].code = LMF$_PROD_DATE;
    itm_lst[0].length = 8;
    itm_lst[0].address = (char *)prod_date;

    itm_lst[1].code = LMF$_PROD_VERSION;
    itm_lst[1].length = 4;
    itm_lst[1].address = (char *)CdaRT_prod_ver;

    itm_lst[2].code = 0;
    itm_lst[2].length = 0;
    itm_lst[2].address = NULL;

    status = sys$lookup_license(&CdaRT_prod_name, itm_lst, &CdaRT_producer,
				&flags, license_context, 0);
    if (status & 1)
       printf ("\nCDA-RT licence found");		 
    else
       printf ("\nCDA-RT licence not found");		 

    status = sys$bintim(&DWMotif_prod_datename, prod_date);
    if (!(status & 1))
       exit (-1);

    itm_lst[0].code = LMF$_PROD_DATE;
    itm_lst[0].length = 8;
    itm_lst[0].address = (char *)prod_date;

    itm_lst[1].code = LMF$_PROD_VERSION;
    itm_lst[1].length = 4;
    itm_lst[1].address = (char *)DWMotif_prod_ver;

    status = sys$lookup_license(&DWMotif_prod_name, itm_lst, &CdaRT_producer,
				&flags, license_context, 0);
    if (status & 1)
       printf ("\nDW-MOTIF licence found");		 
    else
       printf ("\nDW-MOTIF licence not found");		 

    status = sys$lookup_license(&Foo_prod_name, itm_lst, &CdaRT_producer,
				&flags, license_context, 0);
    if (status & 1)
       printf ("\nFoo licence found");		 
    else
       printf ("\nFoo licence not found");		 

}


T.RTitleUserPersonal
Name
DateLines
207.1Working LMF Code...XDELTA::HOFFMANSteve, OpenVMS EngineeringTue Feb 18 1997 12:34120
   Here's some LMF code I've been using over the years...

/*
** COPYRIGHT (c) 1992 BY
** DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS.
** ALL RIGHTS RESERVED.
**
** THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED
** ONLY  IN  ACCORDANCE  OF  THE  TERMS  OF  SUCH  LICENSE  AND WITH THE
** INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR  ANY  OTHER
** COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
** OTHER PERSON.  NO TITLE TO AND  OWNERSHIP OF THE  SOFTWARE IS  HEREBY
** TRANSFERRED.
**
** THE INFORMATION IN THIS SOFTWARE IS  SUBJECT TO CHANGE WITHOUT NOTICE
** AND  SHOULD  NOT  BE  CONSTRUED  AS A COMMITMENT BY DIGITAL EQUIPMENT
** CORPORATION.
**
** DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE  OR  RELIABILITY OF ITS
** SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
*/

/*
**++
**  Facility:
**
**	Examples
**
**  Version: V1.0
**
**  Abstract:
**
**	Example of working with the DEC LMF calls
**
**  Author:
**	Steve Hoffman
**
**  Creation Date:  1-Jan-1990
**
**  Modification History:
**--
*/
/*
// lmf.c
// this subroutine is used to check for a hardwired product license.
// If the license is not installed the soubroutine signals the error.
*/

#include <descrip.h>
#include <lib$routines.h>
#include <lmfdef.h>
#include <ssdef.h>
#include <starlet.h>
#include <stddef.h>
#include <stdio.h>
#include <stsdef.h>
/* until sys$lookup_license() is in starlet.h... */
int sys$lookup_license( void *, void *, void *);

lmf()
    {
    int retstat;
    $DESCRIPTOR( product, "BOGUS" );
    $DESCRIPTOR( producer, "DEC" );
    $DESCRIPTOR( prod_date, "1-JAN-1988" );
    int prod_version = 0x010000;
    int i;
    char bintim[8];
    struct itmlst_3
	{
	short buflen;
	short itmcod;
	void *bufadr;
	void *bufrla;
	} itmlst[3];

    /*
    // Fill in the item list required by the call.  Includes the
    // required final, zero-filled, block.
    */
    i = 0;
    itmlst[i].buflen = 8;
    itmlst[i].itmcod = LMF$_PROD_DATE;
    itmlst[i].bufadr = (void *) bintim;
    itmlst[i++].bufrla = NULL;

    itmlst[i].buflen = 4;
    itmlst[i].itmcod = LMF$_PROD_VERSION;
    itmlst[i].bufadr = (void *) &prod_version;
    itmlst[i++].bufrla = NULL;

    itmlst[i].buflen = 0;
    itmlst[i].itmcod = 0;
    itmlst[i].bufadr = NULL;
    itmlst[i++].bufrla = NULL;

    /*
    // convert the time from ASCII to the internal quadword format.
    */
    retstat = sys$bintim( &prod_date, bintim );
    if ( !$VMS_STATUS_SUCCESS( retstat ))
	lib$signal( retstat );

    /*
    // The LMF signals on errors.
    */
    retstat = sys$lookup_license( &product, &itmlst, &producer );
    if ( !$VMS_STATUS_SUCCESS( retstat ))
	lib$signal( retstat );

    return SS$_NORMAL;
    }

main()
    {
    int retstat;
    retstat = lmf();
    return retstat;
    }
207.2don't forget SHOW LICENSESTAR::ABISEasy as 3.14159265Tue Feb 18 1997 14:1017
The concept that is making things appear mysterious is the fact the LICENSE
LIST tells you what is in the license database file pointed to by the
LMF$LICENSE logical.  SYS$LOOKUP_LICENSE doesn't look there.

SYS$LOOKUP_LICENSE checks license data stored in memory by the LMF.  The LMF
reads the license database file (pointed to by the LMF$LICENSE logical) while
executing a LICENSE START (at system boot time) or LICENSE LOAD command and
stores the data in memory for SYS$LOOKUP_LICENSE.  To see what licenses are in
memory, use the SHOW LICENSE family of commands.

It sounds like to me that your LICENSE LIST command isn't reading the same
license database file your test systems are reading when they boot.  I think
now that you understand the license database file (LICENSE LIST) and in memory
database (SHOW LICENSE) concepts, finding the problem at the customer site
should be a piece 'o cake.

Eric
207.3still baffled...GALVIA::DUKERonanTue Feb 18 1997 14:4428
re .1
Steve,
  I tried your code, just substituting CDA-RT and it does the same: it finds
the CDA-RT license where $ LICENSE LIST and $SHOW LICENSE don't.

re .2
Eric,
  Thanks for the info - I wasn't aware of $SHOW LICENSE.   I went back to my
test machine and $SHOW LICENSE says 
%SHOW-I-NOLICMATCH, no licenses match search criteria
when I look for CDA-RT.
$ LICENSE LIST shows no CDA-RT license on disk either.   Yet, my test program
(and Steve's) both find it.

  The LMF$LICENSE logical is defined to be 
"LMF$LICENSE" = "SYS$COMMON:[SYSEXE]LMF$LICENSE.LDB" (LNM$SYSTEM_TABLE)
  There isn't any other .LDB file on any of the disks.  $SHOW LICENSE show up a
huge amount of licenses - it's just that CDA-RT is not there :-(
                                             
 I've replicated this on my test system (VAX V7.1) and the production system
(VAX V6.1).  As I said earlier, I rebooted the test machine this morning just
to start from scratch.

 Still, the $SHOW LICENSE command may help with the customer situation. 
 But I'm baffled...

thanks for your help,
Ronan
207.4if all else fails, check the group tablesSTAR::ABISEasy as 3.14159265Tue Feb 18 1997 16:098
I should have also mentioned the LMF group tables.  CDA-RT is one of the
products supported by NAS packages on VAX.  So if you have one of the
NET-APP-SUP-%%% PAKs loaded, SYS$LOOKUP_LICENSE will return success.

You can take a peek at the sys$update:vmsinstal_lmfgroups.com file to get an
idea of what products are supported by what group licenses.

Eric
207.5more secrets revealedSTAR::ABISEasy as 3.14159265Tue Feb 18 1997 16:3012
Steve, Ronan,  

For fun, you may want to improve your diagnostic LMF program to request
SYS$LOOKUP_LICENSE to return the name of the license that granted access.  When
dealing with group licenses, this flicks on the light in a dark room.

Simply add two more parameters to your SYS$LOOKUP_LICENSE call, the context (a
pointer to 16 byte buffer) and a pointer to a descriptor pointing to an empty
buffer (at least 24 bytes).  SYS$LOOKUP_LICENSE will write the name of the
license that granted access to your buffer.

Eric
207.6When Did Args Get Added?XDELTA::HOFFMANSteve, OpenVMS EngineeringTue Feb 18 1997 16:4214
:For fun, you may want to improve your diagnostic LMF program to request
:SYS$LOOKUP_LICENSE to return the name of the license that granted access.
:When dealing with group licenses, this flicks on the light in a dark room.

  That LMF code dates back to T5.0 -- I ended up reverse-engineering
  from the OpenVMS sources to get that code to work, and writing up
  a `cookbook' to licensing, part numbers, terminology, etc., and on
  how to get this LMF code to work.  (The then-current documentation
  was pretty buggy...)

  Adding the arguments is definitely a good suggestion, though --  I can
  only assume these arguments were added since I last looked at this...

207.7since day 1, maybe even day 0STAR::ABISEasy as 3.14159265Tue Feb 18 1997 16:587
They have been there since day 1.  I just took a look at the V501_resd$ listing
and they're there.

I guess the documentation for undocumented system services is never as good as
it should be.  :^(

Eric
207.8Even The Code Comments Were Wrong...XDELTA::HOFFMANSteve, OpenVMS EngineeringTue Feb 18 1997 17:126
:I guess the documentation for undocumented system services is never as good as
:it should be.  :^(

   The official manual for this service listed one return buffer as a
   longword, and it actually returned a quadword.  This `stack-stomper'
   took a while to find.
207.9it's after 5, do you know where your stack is?STAR::ABISEasy as 3.14159265Tue Feb 18 1997 20:0415
Besides the product name for the group license, product tokens (by descriptor),
and hardware id (by descriptor), the only other data returned is the context.  

The context parameter is 16 bytes ( LMF$K_CONTEXTLEN ), which is two quadwords.
So perhaps some stacks are being stomped as we speak?

The sys$grant_license system service, which is called by sys$lookup_license
(and all third party applications who aren't allowed to use sys$lookup_license)
to do the actual license checking, is fairly well documented in the PAKGEN
documentation.  But PAKGEN is an orphan product and its docs are now also out
of date.  There was only money to update the LMF Utility manual for LMF V1.2.

ONLY I KNOW ALL THE SECRETS OF LMF [insert maniacal laugh here]!

Sad, isn't it?
207.10a-hahGALVIA::DUKERonanWed Feb 19 1997 09:1511
thanks for the help Eric and Steve.  That indeed solves my problem.  I've got
the NET-APP-SUP-400 license active which was how my CDA-RT was picked up.  The
file SYS$COMMON:[SYSUPD]VMSINSTAL_LMFGROUPS.COM was interesting.
   FYI: I hunted down my copy of the LMF documentation and it includes a
description of the last 2 arguments.   For the context, it specified the type as
longword by reference but the description says "this argument is 16 bytes in
length".

I now see the light...

-ronan