| 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]
|
| 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);
}
|
| 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]>
|
| 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
|