![Content starts here](http://welcome.hp-ww.com/img/s.gif) |
OpenVMS Programming Concepts Manual
- The item list contains five entries:
- Opaque full name of the object with the attribute the program wants
to read
- Type of object to access
- Opaque simple name of the attribute to read
- Address of the buffer containing the set of values returned by the
read operation
- A value of 0 to terminate the item list
- The loop repeatedly calls the SYS$DNSW
service to read the values of the attribute because the first call
might not return all the values. The loop executes until $DNSW returns
something other than DNS$_MOREDATA.
- The DNS$REMOVE_FIRST_SET_VALUE routine
extracts a value from the set.
- This attribute name may be the context the
routine uses to read additional attributes. The attribute's creation
timestamp (CTS), not its value, provides the context.
- Finally, display the value in hexadecimal
format. (You could also take the attribute name and convert it to a
printable format before displaying the result.)
See the discussion about setting confidence in the
Guide to Programming with DECdns for information about obtaining up-to-date data
on read requests.
F.2.3.3 Enumerating DECdns Names and Attributes
The enumerate functions return DECdns names for objects, child
directories, soft links, groups, or attributes in a specific directory.
Use either the asterisk (*) or question mark (?) wildcard to screen
enumerated items. DECdns matches any single character against the
specified wildcard.
Enumeration calls return a set of simple names or attributes. If an
enumeration call returns DNS$_MOREDATA, not all matching names or
attributes have been enumerated. If you receive this message, use the
context-setting conventions that are described for the
DNS$_READ_ATTRIBUTE call. You should make further calls, setting
DNS$_CONTEXTVARNAME to the last value returned until the procedure
returns SS$_NORMAL. For more information, see the SYS$DNS system
service in the OpenVMS System Services Reference Manual: A--GETUAI.
The following program, written in C, shows how an application can read
the objects in a directory with the SYS$DNS system service. The values
that DECdns returns from read and enumerate functions are in different
structures. For example, an enumeration of objects returns different
structures than an enumeration of child directories. To clarify how to
use this data, the sample program demonstrates how to parse any set
that the enumerate objects function returns with a run-time library
routine in order to remove the first value from the set. The example
also demonstrates how the program takes each value from the set.
#include <dnsdef.h>
#include <dnsmsg.h>
/*
* Parameters:
* fname_p : opaque full name of the directory to enumerate
* fname_len : length of full name of the directory
*/
struct $dnsitmdef enumitem[4]; /* Item list for enumeration */
unsigned char setbuf[100]; /* Values from enumeration */
struct $dnsb enum_iosb; /* DECdns status information */
int synch_event; /* Used for synchronous AST threads */
unsigned short setlen; /* Length of output in setbuf */
enumerate_objects(fname_p, fname_len)
unsigned char *fname_p;
unsigned short fname_len;
{
int enumerate_objects_ast();
int status; /* General routine status */
int enum_status; /* Status of enumeration routine */
/* Set up item list */
enumitem[0].dns$w_itm_code = dns$_directory; /* Opaque directory name */
enumitem[0].dns$w_itm_size = fname_len;
enumitem[0].dns$a_itm_address = fname_p;
enumitem[1].dns$w_itm_code = dns$_outobjects; /* output buffer */
enumitem[1].dns$a_itm_ret_length = &setlen;
enumitem[1].dns$w_itm_size = 100;
enumitem[1].dns$a_itm_address = setbuf;
*((int *)&enumitem[2]) = 0; /* Zero terminate item list */
status = lib$get_ef(&synch_event); (1)
if(status != SS$_NORMAL)
{
printf("Could not get event flag to synch AST threads\n");
exit(status);
}
enum_status = sys$dns(0, dns$_enumerate_objects, &enumitem,
(2) &enum_iosb, enumerate_objects_ast, setbuf);
if(enum_status != SS$_NORMAL) (3)
{
printf("Error enumerating objects = %d\n", enum_status);
exit(enum_status);
}
status = sys$synch(synch_event, &enum_iosb); (4)
if(status != SS$_NORMAL)
{
printf("Synchronization with AST threads failed\n");
exit(status);
}
}
/* AST routine parameter: */
/* outbuf : address of buffer that contains enumerated names. */
(5)
unsigned char objnamebuf[dns$k_simplenamemax]; /* Opaque object name */
enumerate_objects_ast(outbuf)
unsigned char *outbuf;
{
struct $dnsitmdef cvtitem[3]; /* Item list for class name */
struct $dnsb iosb; /* Used for name service status information */
struct dsc$descriptor set_dsc, value_dsc, newset_dsc;
unsigned char simplebuf[dns$k_simplestrmax]; /* Object name string */
int enum_status; /* The status of the enumeration itself */
int status; /* Used for checking immediate status returns */
int set_status; /* Status of remove value routine */
unsigned short val_len; /* Length of set value */
unsigned short sname_len; /* Length of object name */
enum_status = enum_iosb.dns$l_dnsb_status; /* Check status */
if((enum_status != SS$_NORMAL) && (enum_status != DNS$_MOREDATA))
{
printf("Error enumerating objects = %d\n", enum_status);
sys$setef(synch_event);
exit(enum_status);
}
do
{
/*
* Extract object names from output buffer one
* value at a time. Set up descriptors for the extraction.
*/
set_dsc.dsc$w_length = setlen; /* Contains address of */
set_dsc.dsc$a_pointer = setbuf; /* the set whose values */
/* are to be extracted */
value_dsc.dsc$w_length = dns$k_simplenamemax;
value_dsc.dsc$a_pointer = objnamebuf; /* To contain the */
/* name of an object */
/* after the extraction */
newset_dsc.dsc$w_length = 100; /* To contain a new */
newset_dsc.dsc$a_pointer = setbuf; /* set structure after */
/* the extraction. */
/* Call yRTL routine to extract the value from the set */
set_status = dns$remove_first_set_value(&set_dsc, &value_dsc, &val_len,
0, 0, &newset_dsc, &setlen);
if(set_status == SS$_NORMAL)
{ (6)
cvtitem[0].dns$w_itm_code = dns$_fromsimplename;
cvtitem[0].dns$w_itm_size = val_len;
cvtitem[0].dns$a_itm_address = objnamebuf;
cvtitem[1].dns$w_itm_code = dns$_tostringname;
cvtitem[1].dns$w_itm_size = dns$k_simplestrmax;
cvtitem[1].dns$a_itm_address = simplebuf;
cvtitem[1].dns$a_itm_ret_length = &sname_len;
*((int *)&cvtitem[2]) = 0;
status = sys$dnsw(0, dns$_simple_opaque_to_string, &cvtitem,
&iosb, 0, 0);
if(status == SS$_NORMAL)
status = iosb.dns$l_dnsb_status; /* Check for errors */
if(status != SS$_NORMAL) /* If error, terminate processing */
{
printf("Converting object name to string returned %d\n",
status);
exit(status);
}
else
{
printf("%.*s\n", sname_len,simplebuf);
}
enumitem[2].dns$w_itm_code = dns$_contextvarname; (7)
enumitem[2].dns$w_itm_size = val_len;
enumitem[2].dns$a_itm_address = objnamebuf;
*((int *)&enumitem[3]) = 0;
}
else if (set_status != 0)
{
printf("Error %d returned when removing value from set\n",
set_status);
exit(set_status);
}
} while(set_status == SS$_NORMAL);
if(enum_status == DNS$_MOREDATA)
{ (8)
enum_status = sys$dns(0, dns$_enumerate_objects, &enumitem,
&enum_iosb, enumerate_objects_ast, setbuf);
if(enum_status != SS$_NORMAL) /* Check status of $DNS */
{
printf("Error enumerating objects = %d\n", enum_status);
sys$setef(synch_event);
}
}
else
{ (9)
sys$setef(synch_event);
}
}
|
- Get an event flag to synchronize the
execution of AST threads.
- Use the system service to enumerate the
object names.
- Check the status of the system service
itself before waiting for threads.
- Use the SYS$SYNCH call to make sure the
DECdns Clerk has completed and that all threads have finished executing.
- After enumerating objects, SYS$DNS calls an
AST routine. The routine shows how DNS$REMOVE_FIRST_SET_VALUE extracts
object names from the set returned by the DNS$_ENUMERATE_OBJECTS
function.
- Use an item list to convert the opaque
simple name to a string name so you can display it to the user. The
item list contains the following entries:
- Address of the opaque simple name to be converted
- Address of the buffer that will hold the string name
- A value of 0 to terminate the item list
- This object name may provide the context for
continuing the enumeration. Append the context variable to the item
list so the enumeration can continue from this name if there is more
data.
- Use the system service to enumerate the
object names as long as there is more data.
- Set the event flag to indicate that all AST
threads have completed and that the program can terminate.
F.3 Using the DCL Command DEFINE with DECdns Logical Names
When the DECdns Clerk is started on the operating system, the VAX
system creates a unique logical name table for DECdns to use in
translating full names. This logical name table, called DNS$SYSTEM,
prevents unintended interaction with other system logical names.
To define systemwide logical names for DECdns objects, you must have
the appropriate privileges to use the DCL command DEFINE. Use the
DEFINE command to create the logical RESEARCH.PROJECT_DISK, for
example, by entering the following DCL command:
$ DEFINE/TABLE=DNS$SYSTEM RESEARCH "ENG.RESEARCH"
|
When parsing a name, the SYS$DNS service specifies the logical name
DNS$LOGICAL as the table it uses to translate a simple name into a full
name. This name translates to DNS$SYSTEM (by default) to access the
systemwide DECdns logical name table.
To define process or job logical names for SYS$DNS, you must create a
process or job table and redefine DNS$LOGICAL as a search list, as in
the following example (note that elevated privileges are required to
create a job table):
$ CREATE /NAME_TABLE DNS_PROCESS_TABLE
$ DEFINE /TABLE=LNM$PROCESS_DIRECTORY DNS$LOGICAL -
_$DNS_PROCESS_TABLE,DNS$SYSTEM
|
Once you have created the process or job table and redefined
DNS$LOGICAL, you can create job-specific logical names for DECdns by
using the DCL command DEFINE, as follows:
$ DEFINE /TABLE=DNS_PROCESS_TABLE RESEARCH "ENG.RESEARCH.MYGROUP"
|
|