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

Conference hydra::axp-developer

Title:Alpha Developer Support
Notice:[email protected], 800-332-4786
Moderator:HYDRA::SYSTEM
Created:Mon Jun 06 1994
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:3722
Total number of notes:11359

3197.0. "Seagate Software (Holistic Systems) - Point 19904" by RDGENG::ASAP () Fri Feb 14 1997 06:00

    Company Name :  Seagate Software (Holistic Systems) - Point 19904
    Contact Name :  Tony Proctor
    Phone        :  44 181 566 2330
    Fax          :  
    Email        :  [email protected]
    Date/Time in :  14-FEB-1997 10:57:58
    Entered by   :  Nick Hudson
    SPE center   :  REO

    Category     :  VMS
    OS Version   :  
    System H/W   :  Alpha


    Brief Description of Problem:
    -----------------------------

  Subject:  Scanning logical name tables
  
Can anyone supply me with a semi-offical way of searching through the items in
a logical name table?

All I'm trying to do is return each logical names from a given table that match
a specified wildcard; a bit like DCL's SHOW LOGICAL/TABLE but programmatically. None of the
services/RTLs seem to offer a 'table search' facility; only translation of a single, explicit
name.

I looked in the VMS internals book to find out the logical name table format
(which looks quite straightforward), but I'm not sure how to get from the table name to the table
address, or how "offical" this approach would be. The code would have to work for both OpenVMS
VAX and OpenVMS Alpha.


T.RTitleUserPersonal
Name
DateLines
3197.1KZIN::HUDSONThat's what I thinkFri Feb 14 1997 11:4545
From:	DEC:.REO.REOVTX::HUDSON       "[email protected] - UK Software
Partner Engineering 830-4121" 14-FEB-1997 16:43:52.28
To:	nm%vbormc::"[email protected]"
CC:	HUDSON
Subj:	RE:POINT No. 19904, Seagate Software (Holistic Systems), wildcard trnlnm

Hello Tony Proctor

>Can anyone supply me with a semi-offical way of searching through the items in
>a logical name table?

I've looked through the internal databases, and the only reference I can find
for this is an old Macro-32 program that purports to do this on VAX.  I'll
attach this to the bottom of this mail fyi.

>I looked in the VMS internals book to find out the logical name table format
>(which looks quite straightforward), but I'm not sure how to get from the
>table name to the table address, or how "offical" this approach would be.

It looks like any solution is going to involve traversing the internal LNM data
structures, and will be unofficial and unsupported.  I.e. if you do it and get
problems then you're on your own.

>The code would have to work for both OpenVMS VAX and OpenVMS  Alpha.

I can't find any corresponding Alpha example, but I'll have a go at digging up
some info for you.  I guess you may find that you'll need at least conditional
compilation to account for possible differences in the layout of structures in
memory (I haven't looked at the sources to check yet).

Regards

Nick Hudson
Digital Software Partner Engineering


Example follows.  Since this returns all the names in a table, you'd use
something like STR$MATCH_WILD to pick out those that are of interest.

This is provided on an as-is basis, not tested at all, no guarantees that it
works or won't crash your system.  I recommend that you use it as an
illustration of a possible approach to solving your problem and not run it
unless you are certain that it will do what you want.

[code from hackers #769 included]
3197.2KZIN::HUDSONThat's what I thinkFri Feb 28 1997 09:38311
From:	DEC:.REO.REOVTX::HUDSON       "[email protected] - UK Software
Partner Engineering 830-4121" 28-FEB-1997 14:37:34.81
To:	nm%vbormc::"[email protected]"
CC:	HUDSON
Subj:	re:point 19904, logical names

Hello Tony Proctor

Further to my last mail I did a bit more looking into your question.

>All I'm trying to do is return each logical names from a given table that match
>a specified wildcard; a bit like DCL's SHOW LOGICAL/TABLE but programmatically.

The problem is that there doesn't seem to be a pointer from the data structure
that describes a logical name table (LNMTH) what logical names it holds.

As you probably know already, LNMB structures are used to describe individual
logical names, and an LNMB has a pointer to the LNMTH for the table in which it
belongs, but there's no pointer back the other way (LNMTH to LNMB).  LNMBs are
linked together using FLINK/BLINKs, but the LNMBs linked in this way are linked
because they have the same hash value, not because they're in the same logical
name table.

So I think you have to use the approach used by the Macro program I sent
earlier - i.e. follow the hash tables that are pointed to by LNM$AL_HASHTBL to
find every logical name on the system, and check each LNMB to find out in which
table it appears.

>The code would have to work for both OpenVMSVAX and OpenVMS Alpha.

I've written a C program which works on Alpha, but this doesn't build on VAX
because VAX VMS doesn't provide SYS$LIB_C.TLB, and if it did I'm not sure all
the structures are compatible.  So I think your options are either to have
different source, or use MACRO-32 and cross-compile that (MACRO/MIGRATE) on
Alpha.  I haven't tried doing that with the earlier example so don't know
whether that will work.


I include the C program I wrote below.  This just prints out every logical name
and the table it's in from the shareable hash table, and the process hash table
for the user who's running it.  Hopefully this could act as an example for you
to build your own code on.  Note I had quite a few system crashes when
developing this code.

I hope this is of some help

Regards

Nick Hudson
Digital Software Partner Engineering

/* lnm.c

   Nick Hudson, Digital

   Build on Alpha VMS using

	$ cc lnm + sys$share:sys$lib_c/tlb
	$ link/sysexe lnm

   Note:
   - Requires CMKRNL to run
   - Does no locking on the logical name table data structures
   - Quite likely to crash the system if it falls off the end of
     a linked list when tracking LNMBs

   See "OpenVMS AXP Internals & Data Structures" chapter on Logical names
   for description of data structures.

*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <lnmdef.h>
#include <lnmstrdef.h>
#include <lnm_routines.h>
#include <ctlp1flagsdef.h>
#include <starlet.h>

extern void 		*CTL$GL_LNMDIRECT;
extern void		*LNM$AL_HASHTBL[2];

// Globals
volatile unsigned int	g_globhashsiz;
volatile unsigned int	g_prochashsiz;

volatile LNMB		**g_shared_hash;
volatile LNMB		**g_process_hash;

volatile char	g_lognam[1024];
volatile char	g_tablename[1024];

LNMB		g_lnmb;

// relies on lognam and tabnam having been allocated and at least
// 512 bytes each big
void decode_lnmb(LNMB *lnmb, volatile char *lognam, volatile char *tabnam)
{
	LNMX	*lnmx;
	LNMTH	*table;
	LNMB	*table_lnmb;
	static  char *tbl = "[logical name table]";
                                        
	lognam[0] = 0;
        tabnam[0] = 0;

	if (lnmb->lnmb$l_namelen == 0) {
		return;
	}

	memcpy(lognam, &lnmb->lnmb$t_name, lnmb->lnmb$l_namelen);
	lognam[lnmb->lnmb$l_namelen] = 0;	// null terminate

	lnmx = lnmb->lnmb$l_lnmx;

	// Various checks return here if anything looks dubious, in an
	// attempt to save accvio'ing while in kernel mode.
	if (lnmx == 0) {
		return;
	}
	
	table = lnmb->lnmb$l_table;
	if (table == NULL) { 
		return;
	}

	table_lnmb = table->lnmth$l_name;
	if (table_lnmb == NULL) {
		return;
	}
       
	if (table_lnmb->lnmb$l_namelen == 0) {
		return;
	}
	memcpy(tabnam, &table_lnmb->lnmb$t_name, table_lnmb->lnmb$l_namelen);
	tabnam[table_lnmb->lnmb$l_namelen] = 0;
	
}

// get_lnmb gets the next valid logical name by looking for the
// next lnmb using static variables to keep track of context.  If
// "reset" param is 1, then that means we start from the beginning.
int get_lnmb(int reset)
{
	static int which_list = 0;		// shareable or process
	static int hash_index = 0;		// where in the list
	static LNMB *next_lnmb = NULL;		// next lnmb to look at

	if (reset == 1) {
		which_list = 0;
		hash_index = 0;

		// Find the first non-zero hash-index
		while (g_shared_hash[hash_index] == NULL) {
			hash_index++;
		}

		// "void *" cast below here to prevent NOTVOLQUAL warning
		next_lnmb = (void *)g_shared_hash[hash_index];
	}

	// Have we got to the end of the list?
	if (next_lnmb == NULL) {
		return 0;
	}

	// get the translation
	decode_lnmb(next_lnmb, g_lognam, g_tablename);

	// advance the lnmb
	next_lnmb = next_lnmb->lnmb$l_flink;

	// Valid flink means we can return
	if (next_lnmb != NULL) {
		return 1;
	}

	// which_list==0 means we're looking at shared table
	if (which_list == 0) {
		hash_index++;

		// work through table looking for a non-null entry.
		while ((hash_index < g_globhashsiz) && (next_lnmb == NULL)) {

		// "void *" cast used below to prevent NOTVOLQUAL warning
			next_lnmb = (void *)g_shared_hash[hash_index];
			if (next_lnmb == NULL) {
				hash_index++;
			}
		}
		if (next_lnmb != NULL) {
			return 1;
		}
		// If next_lnmb was NULL after all that, move on to the
		// process list
		which_list = 1;
		hash_index = 0;

		// Find the first non-zero hash-index
		while (g_process_hash[hash_index] == NULL) {
			hash_index++;
		}

		// "void *" cast used below to prevent NOTVOLQUAL warning
		next_lnmb = (void *)g_process_hash[hash_index];
		return 1;
	}

	hash_index++;
	while ((hash_index < g_prochashsiz) && (next_lnmb == NULL)) {

		// "void *" cast used below to prevent NOTVOLQUAL warning
		next_lnmb = (void *)g_process_hash[hash_index];
		if (next_lnmb == NULL) {
			hash_index++;
		}
	}


	return 1;
			
	
}



// init_search sets up the pointers to the hash tables
int init_search()
{
	struct	hash_table {
		unsigned int 	m_mask;
		unsigned int 	m_reserved1;
		unsigned short	m_size;
		unsigned char 	m_type;
		unsigned char 	m_reserved2;
		volatile LNMB 	*m_first_hash;
	} shareable_hash_table, process_hash_table;



	struct hash_table	*globhashtable;
	struct hash_table	*prochashtable;

	// LNM$AL_HASHTBL is the address of a two longword array.
	// First longword points at address of shareable hash table
	// second longword points at address of process hash table
	// see AXP 1.5 IDSM p 1317

	void	**temp;
	temp = LNM$AL_HASHTBL[0];
	globhashtable = *temp;
	temp = LNM$AL_HASHTBL[1];
	prochashtable = *temp;

	shareable_hash_table = *globhashtable;
	process_hash_table = *prochashtable;

	// Each table has three longwords at the front, and then an
	// array of longwords with addresses of LNMB chains.
	// work out array size using "m_size" field of hash table
	g_globhashsiz = (unsigned int)((shareable_hash_table.m_size / 4) - 3);
	g_prochashsiz = (unsigned int)((process_hash_table.m_size / 4) - 3);

	// Work out the address of the start of each of the arrays of
	// hash entries
	g_shared_hash = (&(globhashtable->m_first_hash));
	g_process_hash = (&(prochashtable->m_first_hash));

	return 1;
}
main()
{
	LNMB top;
	int	stat;
	struct arglst {
		int	num_args;
		void*	arg1;
		void*	arg2;
		void*	arg3;
		void*	arg4;
	} arg;

	arg.num_args = 0;
	arg.arg1 = (void *)1;

	stat = sys$cmkrnl(init_search,&arg);
	printf("stat from init_search was %d\n",stat);

	arg.num_args = 1;
	arg.arg1 = (void *)1;
	stat = sys$cmkrnl(get_lnmb,&arg);

	printf("stat from get_lnmb(1) was %d\n",stat);
	printf("lognam = %s, tabnam = %s\n",
		g_lognam, g_tablename);

	arg.num_args = 1;
	arg.arg1 = (void *)0;
	stat = sys$cmkrnl(get_lnmb,&arg);
	while (stat == 1) {
		printf("lognam = %s, tabnam = %s\n",
		g_lognam, g_tablename);
	
		stat = sys$cmkrnl(get_lnmb,&arg);
	}
	printf("stat was %d\n",stat);

}


3197.3KZIN::HUDSONThat&#039;s what I thinkMon Mar 03 1997 05:1749
From:	VBORMC::"[email protected]" "Tony Proctor"  2-MAR-1997 13:52:04.70
To:	"[email protected] - UK Software Partner Engineering 830-4121
28-Feb-1997 1437 +0000" <[email protected]>
CC:	
Subj:	Re: point 19904, logical names


I was sort of hoping for a non-privileged route as 
our product (Holos) is currently non-privileged. 
It's almost impossible to sell to some sites if 
your product requires special privileges because 
they're so "secure".

Looking at the MACRO code in your previous mail, 
I'm not sure whether it needs CMKRNL because those 
pages are protected against user-mode access, or 
because it has to synchronise access to the logical 
name database before looking at it.

The SHOW LOGICAL functionality, in DCL, seems to do 
everything required. I don't suppose anyone's 
thought of providing a LIB$ interface to this code, 
as for lib$delete_logical and lib$set_logical. A 
lib$list_logical is almost deliberately absent.

	Tony Proctor

% ====== Internet headers and postmarks (see DECWRL::GATEWAY.DOC) ======
% Received: from mail.vbo.dec.com (mail.vbo.dec.com [16.36.208.34]) by
vbormc.vbo.dec.com (8.7.3/8.7) with ESMTP id OAA22787 for
<[email protected]>; Sun, 2 Mar 1997 14:48:31 +0100
% Received: from server21.digital.fr (server21.digital.fr [193.56.15.21]) by
mail.vbo.dec.com (8.7.3/8.7) with ESMTP id OAA18181 for
<[email protected]>; Sun, 2 Mar 1997 14:53:15 +0100 (MET)
% Received: from holossys.com (mrgrumpy.holossys.com [194.201.183.18]) by
server21.digital.fr (8.7.5/8.7) with ESMTP id OAA04800 for
<[email protected]>; Sun, 2 Mar 1997 14:55:48 +0100 (MET)
% Received: by postoffice.holossys.com id <40321>; Sun, 2 Mar 1997 13:41:58 +0000
% Date: Sun, 2 Mar 1997 13:49:58 +0000
% From: Tony Proctor <[email protected]>
% X-Mailer: Mozilla 2.02 (WinNT; I)
% MIME-Version: 1.0
% To: "[email protected] - UK Software Partner Engineering 830-4121
28-Feb-1997 1437 +0000" <[email protected]>
% Subject: Re: point 19904, logical names
% References: <[email protected]>
% Content-Type: text/plain; charset=us-ascii
% Content-Transfer-Encoding: 7bit
% Message-Id: <[email protected]>
3197.4KZIN::HUDSONThat&#039;s what I thinkTue Mar 18 1997 04:3735
From:	DEC:.REO.REOVTX::HUDSON       "[email protected] - UK Software
Partner Engineering 830-4121" 18-MAR-1997 09:36:59.74
To:	nm%VBORMC::"[email protected]"
CC:	HUDSON
Subj:	Re: point 19904, logical names

Hello Tony,

>Looking at the MACRO code in your previous mail, 
>I'm not sure whether it needs CMKRNL because those 
>pages are protected against user-mode access, or 
>because it has to synchronise access to the logical 
>name database before looking at it.

At least some of the data structures are kernel read-only.  I guess that a
program should also be taking out the appropriate lock since it otherwise would
run the risk of the pointer chains being changed by someone else while it's in
the middle of reading.


>The SHOW LOGICAL functionality, in DCL, seems to do 
>everything required. I don't suppose anyone's 
>thought of providing a LIB$ interface to this code, 
>as for lib$delete_logical and lib$set_logical. A 
>lib$list_logical is almost deliberately absent.

Yes, SHOW LOGICAL does the trick.  In fact this feature ("lib$list_logical")
has been requested quite a few times over the past few years, but there is no
indication that it is going to be implemented.  


Regards

Nick Hudson
Digital Software Partner Engineering