![Content starts here](http://welcome.hp-ww.com/img/s.gif) |
OpenVMS Programming Concepts Manual
Appendix F Distributed Name Service Clerk (VAX Only)
This chapter describes the DIGITAL Distributed Name Service (DECdns)
Clerk by introducing the functions of the DECdns (SYS$DNS) system
service and various run-time library routines. It is divided into the
following sections:
Section F.1 describes how to use the portable application
programming interface and the operating system's system service and
run-time library interface.
Section F.2 describes how to use the SYS$DNS system service.
Section F.3 describes how to use the DCL command DEFINE.
F.1 DECdns Clerk System Service
The DECdns Clerk (SYS$DNS) system service provides applications with a
means of assigning networkwide names to system resources. Applications
can use DECdns to name such resources as printers, files, disks, nodes,
servers, and application databases. Once an application has named a
resource using DECdns, the name is available for all users of the
application.
The SYS$DNS system service supports two programming interfaces:
- Portable application programming interface
- System service and run-time library (RTL)
Portable Application Interface
Application designers should select an interface for their application
based on programming language, application base, and the specific
requirements of their application.
The portable interface provides support for applications written in the
C programming language, and it provides a high-level interface with
easy-to-use methods of creating and maintaining DECdns names. Use the
portable interface for applications that must be portable between VAX
systems and the Compaq Tru64 UNIX operating system.
The portable interface is documented in the Guide to Programming with DECdns.
VAX System Services and RTL Routines
The VAX system services and run-time library routines can be used by
applications written in the high-level and midlevel languages listed in
the preface of this document. However, applications that use these
interfaces are limited to the VAX system environment. Use the system
service when an application meets any of the following requirements:
- The application needs the full capabilities, flexibility, and
functions of asynchronous support.
- The application will run as part of a privileged shareable image on
the operating system.
- The application is not written in the C programming language.
The SYS$DNS system service is documented in the
OpenVMS System Services Reference Manual. Before using this system service, familiarize
yourself with the basic operating principles, terms, and definitions
used by DECdns. You can gain a working knowledge of DECdns by reading
about the following topics in the Guide to Programming with DECdns:
- DECdns component operation
- Namespace directories, objects, soft links, groups, and
clearinghouses
- DECdns name syntax
- Attributes
- Clerk caching
- Setting confidence and timeouts
- Recommendations for DECdns application programmers
By understanding these topics, you can proceed more easily with this
chapter, which provides an introduction to the DECdns system service
and run-time library routines and discusses the following topics:
- Functions provided by the service and routines
- How to use the SYS$DNS system service
F.1.1 Using the DECdns System Service and Run-Time Library Routines
You can use the SYS$DNS system service and run-time library routines
together to assign, maintain, and retrieve DECdns names. This section
describes the capabilities of each interface.
F.1.1.1 Using the SYS$DNS System Service
DECdns provides a single system service call (SYS$DNS) to create,
delete, modify, and retrieve DECdns names from a namespace. The SYS$DNS
system service completes asynchronously; that is, it returns to the
client immediately after making a name service call. The status
returned to the client indicates whether a request was queued
successfully to the name service.
The SYS$DNSW system service is the synchronous equivalent of SYS$DNS.
The SYS$DNSW call is identical to SYS$DNS in every way except that
SYS$DNSW returns to the caller after the operation completes.
The SYS$DNS call has two main parameters:
- A function code that identifies the particular service to perform
- An item list that specifies all the parameters for the required
function
The system service provides the following functions:
- Create and delete DECdns names in the namespace
- Enumerate DECdns names in a particular directory
- Add, read, remove, and test attributes and attribute values
- Add, create, remove, restore, and update directories
- Create, remove, and resolve soft links
- Create and remove groups
- Add, remove, and test members in a group
- Parse names to convert string format names to DECdns opaque format
names and back to string
You specify item codes as either input or output parameters in the item
list. Input parameters modify functions, set context, or describe the
information to be returned. Output parameters return the requested
information.
You can specify the following in input item codes:
- An attribute name and type
- The class of a DECdns name and, optionally, a class filter
- The class version of a DECdns name
- A confidence setting to indicate whether the request should be
serviced from the clerk's cache or from a server
- An indication that the application will repeat a read call, which
forces caching of recently read data
- A name or timestamp that sets the context from which to begin or
restart enumerating or reading
- The name and type of an object, directory, group, member,
clearinghouse, or soft link, and the ability to suppress the namespace
nickname from the full name
- A simple or full name in opaque or string format
- A request to search subgroups for a member
- An operation, either adding or deleting an attribute
- A value for an attribute
- A pointer to the address of the next character in a full or simple
name
- A timeout period to wait for a call to complete
- An expiration time and extension time for soft links
The output item codes return the following information:
- A creation timestamp for an object
- A set of child directories, soft links, attribute names, attribute
values, or object names
- An opaque simple or full name
- A string name and length
- A resolved soft link
- A name or timestamp context variable that indicates the last
directory, object, soft link, or attribute that was enumerated or read
F.1.1.2 Using the Run-Time Library Routines
You can use the DECdns run-time library routines to manipulate output
from the SYS$DNS system service. The routines provide the following
functions:
- Remove a value from a set returned by an enumeration or read system
service function
- Compare, append, concatenate, and count opaque names that were
created with the system service
- Convert addresses
To read a single attribute value using the system service and run-time
library routines, use the following routines:
- DNS$_ENUMERATE_OBJECTS function code to enumerate objects
- DNS$REMOVE_FIRST_SET_VALUE run-time library routine to remove the
first set value
- DNS$_READ_ATTRIBUTE function code to read the first set value
You can also use the system service and run-time library routines
together to add an opaque simple name to a full name by performing the
following steps:
- Obtain a string full name from a user.
- Use the system service DNS$_PARSE_FULLNAME_STRING function code to
convert the string name to opaque format.
- Use the DNS$_APPEND_SIMPLE_TO_RIGHT run-time library routine to add
an opaque simple name to the end of the full name.
F.2 Using the SYS$DNS System Service Call
The following sections describe how to create and modify an object, and
then how to read attributes and enumerate names and attributes in the
namespace.
Each section contains a code example. These code examples are all
contained in the sample program that resides on your distribution
medium under the file name SYS$EXAMPLES:SYS$DNS_SAMPLE.C.
F.2.1 Creating Objects
Applications that use DECdns can create an object in the namespace for
each resource used by the application. You can create objects using
either the SYS$DNS or the SYS$DNSW system service.
A DECdns object consists of a name and its associated attributes. When
you create the object, you must assign a class and a class version. You
can modify the object to hold additional attributes, such as
class-specific attributes, on an as-needed basis.
Note that applications can use objects that are created by other
applications.
To create an object in the namespace with SYS$DNS:
- Prompt the user for a name.
The name that an application
assigns to an object should come from a user, a configuration file, a
system logical name, or some other source. The application never
assigns an object's name because the namespace structure is uncertain.
The name the application receives from the user is in string format.
- Use the SYS$DNS parse function to convert the full name string into
an opaque format. Specify the DNS$_NEXTCHAR_PTR item code to obtain the
length of the opaque name.
- Optionally, reserve an event flag so you can check for completion
of the service.
- Build an item list that contains the following elements:
- The opaque name for the object (resulting from the translation in
step 2)
- The class name given by the application, which should contain the
facility code
- The class version assigned by the application
- An optional timeout value that specifies when the call expires
- Optionally, provide the address of the DECdns status block to
receive status information from the name service.
- Optionally, provide the address of the asynchronous system trap
(AST) service routine. AST routines allow a program to continue
execution while waiting for parts of the program to complete.
- Optionally, supply a parameter to pass to the AST routine.
- Call the create object function and provide all the parameters
supplied in steps 1 through 7.
If a clerk call is not complete when timeout occurs, then the call
completes with an error. The error is returned in the DECdns status
block.
An application should check for errors that are returned; it is not
enough to check the return of the SYS$DNS call itself. You need to
check the DECdns status block to be sure no errors are returned by the
DECdns server.
The following routine, written in C, shows how to create an object in
the namespace with the synchronous service SYS$DNSW. The routine
demonstrates how to construct an item list.
#include <dnsdef.h>
#include <dnsmsg.h>
/*
* Parameters:
* class_name = address of the opaque simple name of the class
* to assign to the object
* class_len = length (in bytes) of the class opaque simple name
* object_name= address of opaque full name of the object
* to create in the namespace.
* object_len = length (in bytes) of the opaque full name of the
* object to create
*/
create_object(class_name, class_len, object_name, object_len)
unsigned char *class_name; /*Format is a DECdns opaque simple name*\
unsigned short class_len;
unsigned char *object_name; /*Format is a DECdns opaque simple name*\
unsigned short object_len;
{
struct $dnsitmdef createitem[4]; /* Item list used by system service */
struct $dnscversdef version; /* Version assigned to the object */
struct $dnsb iosb; /* Used to determine DECdns server status */
int status; /* Status return from system service */
/*
* Construct the item list that creates the object:
*/
createitem[0].dns$w_itm_size = class_len; (1)
createitem[0].dns$w_itm_code = dns$_class;
createitem[0].dns$a_itm_address = class_name;
createitem[1].dns$w_itm_size = object_len; (2)
createitem[1].dns$w_itm_code = dns$_objectname;
createitem[1].dns$a_itm_address = object_name;
version.dns$b_c_major = 1; (3)
version.dns$b_c_minor = 0;
createitem[2].dns$w_itm_size = sizeof(struct $dnscversdef); (4)
createitem[2].dns$w_itm_code = dns$_version;
createitem[2].dns$a_itm_address = &version;
*((int *)&createitem[3]) = 0; (5)
status = sys$dnsw(0, dns$_create_object, &createitem, &iosb, 0, 0); (6)
if(status == SS$_NORMAL)
{
status = iosb.dns$l_dnsb_status; (7)
}
return(status);
}
|
- The first entry in the item list is the
address of the opaque simple name that represents the class of the
object.
- The second entry is the address of the
opaque full name for the object.
- The next step is to build a version
structure that indicates the version of the object. In this case, the
object is version 1.0.
- The third entry is the address of the
version structure that was just built.
- A value of 0 terminates the item list.
- The next step is to call the system service
to create the object.
- Check to see that both the system service
and DECdns were able to perform the operation without error.
F.2.2 Modifying Objects and Their Attributes
After you create objects that identify resources, you can add or modify
attributes that describe properties of the object. There is no limit
imposed on the number of attributes an object can have.
You modify an object whenever you need to add an attribute or attribute
value, change an attribute value, or delete an attribute or attribute
value. When you modify an attribute, DECdns updates the timestamp
contained in the DNS$UTS attribute for that attribute.
To modify an attribute or attribute value, use the
DNS$_MODIFY_ATTRIBUTE function code. Specify the attribute name in the
input item code along with the following required input item codes:
- DNS$_ATTRIBUTETYPE to specify a set-valued (DNS$K_SET) or
single-valued (DNS$K_SINGLE) attribute
- DNS$_MODOPERATION to specify that the value is being added
(DNS$K_PRESENT) or deleted (DNS$K_ABSENT)
Use the DNS$_MODVALUE item code to specify the value of the attribute.
Note that the DNS$_MODVALUE item code must be specified to add a
single-valued attribute. You can specify a null value for a set-valued
attribute. DECdns modifies attribute values in the following way:
- If the attribute exists and you specify an attribute value, the
attribute value is removed from a set-valued attribute. All other
values are unaffected. For a single-valued attribute, DECdns removes
the attribute and its value from the name.
- If you do not specify an attribute value, DECdns removes the
attribute and all values of the attribute for both set-valued and
single-valued attributes.
To delete an attribute, use the DNS$_MODOPERATION item code.
The following is an example of how to use the DNS$_MODIFY_ATTRIBUTE
function code to add a new member to a group object. To do this, you
add the new member to the DNS$Members attribute of the group object.
Use the following function codes:
- Specify the group object (DNS$_ENTRY) and type (DNS$_LOOKINGFOR).
The type should be specified as object (DNS$K_OBJECT).
- Use DNS$_MODOPERATION to add a member to the DNS$Members attribute
(DNS$_ATTRIBUTENAME), which is a set-valued attribute
(DNS$_ATTRIBUTETYPE).
- Specify the new member object name in DNS$_MODVALUE.
- Use another DNS$_MODIFY_ATTRIBUTE call to assign access rights for
the new member to the DNS$ACS attribute of the member object.
Perform the following steps to modify an object with SYS$DNSW:
- Build an item list that contains the following elements:
- Opaque name of the object you are modifying
- Type of object
- Operation to perform
- Type of attribute you are modifying
- Attribute name
- Value being added to the attribute
- Supply any of the optional parameters described in Section F.2.1.
- Call the modify attribute function, supplying the parameters
established in steps 1 and 2.
The following example, written in C, shows how to add a set-valued
attribute and a value to an object:
#include <dnsdef.h>
#include <dnsmsg.h>
/*
* Parameters:
* obj_name = address of opaque full name of object
* obj_len = length of opaque full name of object
* att_name = address of opaque simple name of attribute to create
* att_len = length of opaque simple name of attribute
* att_value= value to associate with the attribute
* val_len = length of added value (in bytes)
*/
add_attribute(obj_name, obj_len, att_name, att_len, att_value, val_len)
unsigned char *obj_name;
unsigned short obj_len;
unsigned char *att_name;
unsigned short att_len;
unsigned char *att_value;
unsigned short val_len;
main() {
struct $dnsitmdef moditem[7]; /* Item list for $DNSW */
unsigned char objtype = dns$k_object; /* Using objects */
unsigned char opertype = dns$k_present; /* Adding an object */
unsigned char attype = dns$k_set; /* Attribute will be type set */
struct $dnsb iosb; /* Used to determine DECdns status */
int status; /* Status of system service */
/*
* Construct the item list to add an attribute to an object.
*/
moditem[0].dns$w_itm_size = obj_len;
moditem[0].dns$w_itm_code = dns$_entry;
moditem[0].dns$a_itm_address = obj_name; (1)
moditem[1].dns$w_itm_size = sizeof(char);
moditem[1].dns$w_itm_code = dns$_lookingfor;
moditem[1].dns$a_itm_address = &objtype; (2)
moditem[2].dns$w_itm_size = sizeof(char);
moditem[2].dns$w_itm_code = dns$_modoperation;
moditem[2].dns$a_itm_address = &opertype; (3)
moditem[3].dns$w_itm_size = sizeof(char);
moditem[3].dns$w_itm_code = dns$_attributetype;
moditem[3].dns$a_itm_address = &attype; (4)
moditem[4].dns$w_itm_size = att_len;
moditem[4].dns$w_itm_code = dns$_attributename;
moditem[4].dns$a_itm_address = att_name; (5)
moditem[5].dns$w_itm_size = val_len;
moditem[5].dns$w_itm_code = dns$_modvalue;
moditem[5].dns$a_itm_address = att_value; (6)
*((int *)&moditem[6]) = 0; (7)
/*
* Call $DNSW to add the attribute to the object.
*/
status = sys$dnsw(0, dns$_modify_attribute, &moditem, &iosb, 0, 0);(8)
if(status == SS$_NORMAL)
{
status = iosb.dns$l_dnsb_status; (9)
}
return(status);
}
|
- The first entry in the item list is the
address of the opaque full name of the object.
- The second entry shows that this is an
object, not a soft link or child directory pointer.
- The third entry is the operation to perform.
The program adds an attribute with its value to the object.
- The fourth entry is the attribute type. The
attribute has a set of values rather than a single value.
- The fifth entry is the opaque simple name of
the attribute being added.
- The sixth entry is the value associated with
the attribute.
- A value of 0 terminates the item list.
- A call is made to the SYS$DNSW system
service to perform the operation.
- A check is made to see that both the system
service and DECdns performed the operation without error.
F.2.3 Requesting Information from DECdns
Once an application adds its objects to the namespace and modifies the
names to contain all necessary attributes, the application is ready to
use the namespace. An application can request that the DECdns Clerk
either read attribute information stored with an object or list all the
application's objects that are stored in a particular directory. An
application might also need to resolve all soft links in a name in
order to identify a target.
To request information from DECdns, use the read or enumerate function
codes, as follows:
- The DNS$_READ_ATTRIBUTE function reads and returns a set whose
members are the values of the specified attribute.
- The DNS$_ENUMERATE functions return a list of names for attributes,
child directories, objects, and soft links.
F.2.3.1 Using the Distributed File Service (DFS)
The VAX Distributed File Service (DFS) uses DECdns for resource naming.
This section gives an example of the DNS$_READ_ATTRIBUTE call as used
by DFS. The DFS application uses DECdns to give the operating system's
users the ability to use remote operating system disks as if the disks
were attached to their local VAX system. The DFS application creates
DECdns names for the operating system's directory structures (a
directory and all of its subdirectories). Each DFS object in the
namespace references a particular file access point. DFS creates each
object with a class attribute of DFS$ACCESSPOINT and modifies the
address attribute (DNS$Address) of each object to hold the DECnet node
address where the directory structures reside. As a final step in
registering its resources, DFS creates a database that maps DECdns
names to the appropriate operating system directory structures.
Whenever the DFS application receives the following mount request, DFS
sends a request for information to the DECdns Clerk:
MOUNT ACCESS_POINT dns-name vms-logical-name
|
To read the address attribute of the access point object, the DFS
application performs the following steps:
- Translates the DECdns name that is supplied through the user to
opaque format using the SYS$DNS parse function
- Reads the class attribute of the object with the $DNS read
attribute function, indicating that there is a second call to read
other attributes of the object
- Makes a second call to the SYS$DNS read attribute function to read
the address attribute of the object
- Sends the DECdns name to the DFS server, which looks up the disk on
which the access point is located
- Verifies that the DECdns name is valid on the DFS server
The DFS client and DFS server now can communicate to complete the mount
function.
F.2.3.2 Reading Attributes from DNS
When requesting information from DNS, an application always takes an
object name from the user, translates the name into opaque format, and
passes it in an item list to the DECdns Clerk.
Each read request returns a set of attribute values. The
DNS$_READ_ATTRIBUTE service uses a context item code called
DNS$_CONTEXTVARTIME to maintain context when reading the attribute
values. The context item code saves the last member that is read from
the set. When the next read call is issued, the item code sets the
context to the next member in the set, reads it, and returns it. The
context item code treats single-valued attributes as though they were a
set of one.
If an enumeration call returns DNS$_MOREDATA, not all matching names or
attributes have been enumerated. If you receive this message, you
should make further calls, setting DNS$_CONTEXTVARTIME to the last
value returned until the procedure returns SS$_NORMAL.
The following program, written in C, shows how an application reads an
object attribute. The SYS$DNSW service uses an item list to return a
set of objects. Then the application calls a run-time library routine
to read each value in the set.
#include <dnsdef.h>
#include <dnsmsg.h>
/*
* Parameters:
* opaque_objname = address of opaque full name for the object
* containing the attribute to be read
* obj_len = length of opaque full name of the object
* opaque_attname = address of the opaque simple name of the
* attribute to be read
* attname_len = length of opaque simple name of attribute
*/
read_attribute(opaque_objname, obj_len, opaque_attname, attname_len)
unsigned char *opaque_objname;
unsigned short obj_len;
unsigned char *opaque_attname;
unsigned short attname_len;
{
struct $dnsb iosb; /* Used to determine DECdns status */
char objtype = dns$k_object; /* Using objects */
struct $dnsitmdef readitem[6]; /* Item list for system service */
struct dsc$descriptor set_dsc, value_dsc, newset_dsc, cts_dsc;
unsigned char attvalbuf[dns$k_maxattribute]; /* To hold the attribute */
/* values returned from extraction routine. */
unsigned char attsetbuf[dns$k_maxattribute]; /* To hold the set of */
/* attribute values after the return from $DNSW. */
unsigned char ctsbuf[dns$k_cts_length]; /* Needed for context of multiple reads */
int read_status; /* Status of read attribute routine */
int set_status; /* Status of remove value routine */
int xx; /* General variable used by print routine */
unsigned short setlen; /* Contains current length of set structure */
unsigned short val_len; /* Contains length of value extracted from set */
unsigned short cts_len; /* Contains length of CTS extracted from set */
/* Construct an item list to read values of the attribute. */ (1)
readitem[0].dns$w_itm_code = dns$_entry;
readitem[0].dns$w_itm_size = obj_len;
readitem[0].dns$a_itm_address = opaque_objname;
readitem[1].dns$w_itm_code = dns$_lookingfor;
readitem[1].dns$w_itm_size = sizeof(char);
readitem[1].dns$a_itm_address = &objtype;
readitem[2].dns$w_itm_code = dns$_attributename;
readitem[2].dns$a_itm_address = opaque_attname;
readitem[2].dns$w_itm_size = attname_len;
readitem[3].dns$w_itm_code = dns$_outvalset;
readitem[3].dns$a_itm_ret_length = &setlen;
readitem[3].dns$w_itm_size = dns$k_maxattribute;
readitem[3].dns$a_itm_address = attsetbuf;
*((int *)&readitem[4]) = 0;
do (2)
{
read_status = sys$dnsw(0, dns$_read_attribute, &readitem, &iosb, 0, 0);
if(read_status == SS$_NORMAL)
{
read_status = iosb.dns$l_dnsb_status;
}
if((read_status == SS$_NORMAL) || (read_status == DNS$_MOREDATA))
{
do
{
set_dsc.dsc$w_length = setlen;
set_dsc.dsc$a_pointer = attsetbuf; /* Address of set */
value_dsc.dsc$w_length = dns$k_simplenamemax;
value_dsc.dsc$a_pointer = attvalbuf; /* Buffer to hold */
/* attribute value */
cts_dsc.dsc$w_length = dns$k_cts_length;
cts_dsc.dsc$a_pointer = ctsbuf; /* Buffer to hold value's CTS*/
newset_dsc.dsc$w_length = dns$k_maxattribute;
newset_dsc.dsc$a_pointer = attsetbuf; /* Same buffer for */
/* each call */
set_status = dns$remove_first_set_value(&set_dsc, &value_dsc,
(3) &val_len, &cts_dsc,
&cts_len, &newset_dsc,
&setlen);
if(set_status == SS$_NORMAL)
{ (4)
readitem[4].dns$w_itm_code = dns$_contextvartime;
readitem[4].dns$w_itm_size = cts_len;
readitem[4].dns$a_itm_address = ctsbuf;
*((int *)&readitem[5]) = 0;
printf("\tValue: "); (5)
for(xx = 0; xx < val_len; xx++)
printf("%x ", attvalbuf[xx]);
printf("\n");
}
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);
}
else
{
printf("Error reading attribute = %d\n", read_status);
exit(read_status);
}
} while(read_status == DNS$_MOREDATA);
}
|
|