System Administration Guide: Naming and Directory Services (FNS and NIS+)

Namespace Browser Programming Examples

The programming examples in this section shows the usage of XFN APIs to perform the following operations:

Listing Names Bound in a Context

The example below shows XFN operations to list a context.


#include <stdio.h>
#include <xfn/xfn.h>
#include <string.h>
#include <stdlib.h>
/*
 This routine returns the list of names
 bound under the given context (ctx_name).
 Examples of ctx_name are "user", "thisorgunit/service",
	host/alto/service, user/jsmit/service/calendar, etc.,
*/
typedef struct fns_listing {
	char *name;
	struct fns_listing *next;
} fns_listing;
fns_listing *
fns_list_names(const char *ctx_name)
{
	FN_status_t *status;
	FN_ctx_t *initial_context;
	FN_composite_name_t *context_name;
	FN_namelist_t *name_list;
	FN_string_t *name;
	unsigned int stat;
	fns_listing *head = 0, *current, *prev;
	int no_names = 0;
	status = fn_status_create();
	/* Obtain the initial context */
	initial_context = fn_ctx_handle_from_initial(0, status);
	if (!fn_status_is_success(status)) {
		fprintf(stderr, "Unable to obtain intial context\n");
		return (0);
	}
	context_name = fn_composite_name_from_str((unsigned char *)
                  ctx_name);
	/* FNS call to list names */
	name_list = fn_ctx_list_names(initial_context, context_name,
               status);
	if (!fn_status_is_success(status)) {
		fprintf(stderr, "Unable to list names\n");
		return (0);
	}
	/* Obtain the names individually */
	while (name = fn_namelist_next(name_list, status)) {
		no_names++;
		current = (fns_listing *) malloc(sizeof(fns_listing));
		current->name = (char *)
		 malloc(strlen((char *) fn_string_str(name, &stat)) + 1);
		strcpy(current->name, (char *) fn_string_str(name, &stat));
		current->next = 0;
		if (head) {
			prev->next = current;
			prev = current;
		} else {
			head = current;
			prev = current;
		}
		fn_string_destroy(name);
	}
	fn_namelist_destroy(name_list);
	fn_status_destroy(status);
	fn_ctx_destroy(initial_context);
	return (head);

Creating a Binding

Example 25–1 shows how to create a binding.


Example 25–1 Creating a Binding


#include <stdio.h>
#include <xfn/xfn.h>
#include <string.h>
/*
 This routine creates a binding with a name provided by "name"
 and having a reference type "reference_type" and address type
 "address_type".
 An example of using the function could be:
	 fns_create_bindings(
	 "user/jsmith/service/calendar",
	 "onc_calendar",
	 "onc_cal_str",
	 "jsmith&calserver");
*/
int fns_create_bindings(
 char *name,
 char *reference_type,
 char *address_type,
 char *data)
{
	int return_status;
	FN_composite_name_t *binding_name;
	FN_identifier_t ref_id, addr_id;
	FN_status_t *status;
	FN_ref_t *reference;
	FN_ref_addr_t *address;
	FN_ctx_t *initial_context;
	/* Obtain the initial context */
	status = fn_status_create();
	initial_context = fn_ctx_handle_from_initial(0, status);
	/* Check status for any error messages */
	if ((return_status = fn_status_code(status)) != FN_SUCCESS) {
		fprintf(stderr, "Unable to obtain the initial context\n");
		return (return_status);
	}
	/* Get the composite name for the printer name */
	binding_name = fn_composite_name_from_str((unsigned char *) name);
	/* Construct the Address */
	addr_id.format = FN_ID_STRING;
	addr_id.length = strlen(address_type);
	addr_id.contents = (void *) address_type;
	address = fn_ref_addr_create(&addr_id,
		strlen(data), (const void *) data);
	/* Construct the Reference */
	ref_id.format = FN_ID_STRING;
	ref_id.length = strlen(reference_type);
	ref_id.contents = (void *) reference_type;
	reference = fn_ref_create(&ref_id);
	/* Add Address to the Reference */
	fn_ref_append_addr(reference, address);
	
	/* Create a binding */
	fn_ctx_bind(initial_context, binding_name, reference, 0, status);
	/* Check the error status and return */
	return_status = fn_status_code(status);
	fn_composite_name_destroy(binding_name);
	fn_ref_addr_destroy(address);
	fn_ref_destroy(reference);
	fn_ctx_destroy(initial_context);
	return (return_status);
}

Listing and Working Wtih Object Attributes

The examples below show techniques to list and work with attributes of an object.

Listing an Object's Attributes

The example below shows how to list the attributes of an object.


#include <stdio.h>
#include <xfn/xfn.h>
/*
 This routine prints all the attributes associated
 with the named object to the standard output.
 Examples of using the function:
 	fns_attr_list("user/jsmith");
	fns_attr_list("thisorgunit/service/printer/color");
*/
void fns_attr_list(const char *name)
{
	FN_composite_name_t *name_comp;
	const FN_identifier_t *identifier;
	FN_attribute_t *attribute;
	const FN_attrvalue_t *values;
	char *id, *val;
	FN_multigetlist_t *attrset;
	void *ip;
	FN_status_t *status;
	FN_ctx_t *initial_context;
	name_comp = fn_composite_name_from_str((unsigned char *) name);
	status = fn_status_create();
	/* Obtain the initial context */
	initial_context = fn_ctx_handle_from_initial(0, status);
	if (!fn_status_is_success(status)) {
		fprintf(stderr, "Unable to obtain intial context\n");
		return;
	}
	/* Obtain all the attributes */
	attrset = fn_attr_multi_get(initial_context, name_comp, 0, 0,
            status);
	if (!fn_status_is_success(status)) {
		fprintf(stderr, "Unable to obtain attributes\n");
		return;
	}
	/* List all attributes */
	while (attribute = fn_multigetlist_next(attrset, status)) {
		identifier = fn_attribute_identifier(attribute);
		switch(identifier->format) {
		case FN_ID_STRING:
			id = (char *) malloc(identifier->length + 1);
			memcpy(id, identifier->contents, identifier->length);
			id[identifier->length] = '\0';
			printf("Attribute Identifier: %s", id);
			free(id);
			break;
		default:
			printf("Attribute of non-string format\n\n");
			continue;
		}
		for (values = fn_attribute_first(attribute, &ip);
		 values != NULL;
		 values = fn_attribute_next(attribute, &ip)) {
			val = (char *) malloc(values->length + 1);
			memcpy(val, values->contents, values->length);
			val[values->length] = '\0';
			printf("Value: %s", val);
			free(val);
		}
		fn_attribute_destroy(attribute);
		printf("\n");
	}
	fn_multigetlist_destroy(attrset);
	fn_ctx_destroy(initial_context);
	fn_status_destroy(status);
	fn_composite_name_destroy(name_comp);
}

Adding, Deleting, and Modifying an Object's Attributes

The example below shows how to add, delete, or modify an object's attributes.


#include <stdio.h>
#include <xfn/xfn.h>
/*
 This routine modifies an attribute associated
 with the named object. The modify operation supported are:
 	FN_ATTR_OP_ADD
 FN_ATTR_OP_ADD_EXCLUSIVE
 FN_ATTR_OP_REMOVE
 FN_ATTR_OP_ADD_VALUES
 FN_ATTR_OP_REMOVE_VALUES
 The function assumes the attribute values to be strings.
 Examples of using the function:
 The following function add an attribute of identifier "realname"
 with value "James Smith" to the user object "user/jsmith".
 	fns_attr_modify(
		"user/jsmith",
		"realname",
		"James Smith",
		FN_ATTR_OP_ADD);
 The following function removes an attribute of identifier 
 "location" from the printer object 
 "thisorgunit/service/printer/color".
 	fns_attr_modify(
		"thisorgunit/service/printer/color",
		"location",
		NULL,
		FN_ATTR_OP_REMOVE);
*/
static const char *attr_id_syntax = "fn_attr_syntax_ascii";
void fns_attr_modify(const char *name,
	const char *attr_id,
	const char *attr_value,
	unsigned int operation)
{
	FN_composite_name_t *name_comp;
	FN_identifier_t identifier, syntax;
	FN_attrvalue_t *values;
	FN_attribute_t *attribute;
	FN_status_t *status;
	FN_ctx_t *initial_context;
	name_comp = fn_composite_name_from_str((unsigned char *) name);
	status = fn_status_create();
	/* Obtain the initial context */
	initial_context = fn_ctx_handle_from_initial(0, status);
	if (!fn_status_is_success(status)) {
		fprintf(stderr, "Unable to obtain intial context\n");
		return;
	}
	/* Create the attribute to be added */
	/* First, the identifier */
	identifier.format = FN_ID_STRING;
	identifier.length = strlen(attr_id);
	identifier.contents = (void *) strdup(attr_id);
	/* Second, the syntax */
	syntax.format = FN_ID_STRING;
	syntax.length = strlen(attr_id_syntax);
	syntax.contents = (void *) strdup(attr_id_syntax);
	/* Third, the attribute value */
	if (attr_value) {
		values = (FN_attrvalue_t *) malloc(sizeof(FN_attrvalue_t));
		values->length = strlen(attr_value);
		values->contents = (void *) strdup(attr_value);
	} else
		values = NULL;
	/* Fourth, create the attribute */
	attribute = fn_attribute_create(&identifier, &syntax);
	/*Fifth, add the attribute value */
	if (values)
		fn_attribute_add(attribute, values, 0);
	
	/* Perform the XFN operation */
	fn_attr_modify(initial_context, name_comp, operation, attribute, 0,
status);
	if (!fn_status_is_success(status))
		fprintf(stderr, "Unable to perform attribute operation\n");
	fn_ctx_destroy(initial_context);
	fn_status_destroy(status);
	fn_composite_name_destroy(name_comp);
	fn_attibute_destroy(attribute);
	free(identifier.contents);
	free(syntax.contents);
	if (values) {
		free(values->contents);
		free(values);
 ]
]

Searching for Objects in a Context

The example below shows how to search for objects in a context with a specific attribute identifier and value.


#include <stdio.h>
#include <xfn/xfn.h>
#include <string.h>
#include <stdlib.h>
/*
 This routine searchs for objects in a context
 which has the specified attribute identifier and value.
*/
typedef struct fns_search_results {
	char *name;
	struct fns_search_results *next;
} fns_search_results;
static const char *attr_id_syntax = "fn_attr_syntax_ascii";
fns_search_results *
fns_attr_search(const char *name,
	const char *attr_id,
	const char *attr_value)
{
	FN_status_t *status;
	FN_ctx_t *initial_context;
	FN_composite_name_t *context_name;
	FN_searchlist_t *search_list;
	FN_string_t *search_name;
	FN_attribute_t *attribute;
	FN_attrset_t *attrset;
	FN_identifier_t identifier, syntax;
	FN_attrvalue_t *values;
	unsigned stat;
	fns_search_results *head = 0, *current, *prev;
	int no_names = 0;
	context_name = fn_composite_name_from_str((unsigned char *) name);
	status = fn_status_create();
	initial_context = fn_ctx_handle_from_initial(0, status);
	if (!fn_status_is_success(status)) {
		fprintf(stderr, "Unable to obtain intial context\n");
		return (0);
	}
	/* Construnct the attrset with attributes to be searched */
	/* First, the identifier */
	identifier.format = FN_ID_STRING;
	identifier.length = strlen(attr_id);
	identifier.contents = (void *) strdup(attr_id);
	/* Second, the syntax */
	syntax.format = FN_ID_STRING;
	syntax.length = strlen(attr_id_syntax);
	syntax.contents = (void *) strdup(attr_id_syntax);
	/* Third, the attribute value */
	values = (FN_attrvalue_t *) malloc(sizeof(FN_attrvalue_t));
	values->length = strlen(attr_value);
	values->contents = (void *) strdup(attr_value);
	/* Fourth, create the attribute */
	attribute = fn_attribute_create(&identifier, &syntax);
	/* Fifth, add the attribute value */
	fn_attribute_add(attribute, values, 0);
	/* Sixth, create attrset, and add the attribute */
	attrset = fn_attrset_create();
	fn_attrset_add(attrset, attribute, 0);
	search_list = prelim_fn_attr_search(initial_context,
	 context_name, attrset, 0, 0, status);
	if (!fn_status_is_success(status)) {
		fprintf(stderr, "Unable to list names\n");
		return (0);
	}
	while (search_name = prelim_fn_searchlist_next(search_list,
	 0, 0, status)) {
		no_names++;
		current = (fns_search_results *) 
    malloc(sizeof(fns_search_results));
		current->name = (char *)
		 malloc(strlen((char *) fn_string_str(search_name, &stat)) + 1);
		strcpy(current->name, (char *) fn_string_str(search_name, &stat));
		current->next = 0;
		if (head) {
			prev->next = current;
			prev = current;
		} else {
			head = current;
			prev = current;
		}
		fn_string_destroy(search_name);
	}
	fn_searchlist_destroy(search_list);
	fn_status_destroy(status);
	fn_ctx_destroy(initial_context);
	fn_attrset_destroy(attrset);
	fn_attribute_destroy(attribute);
	free(identifier.contents);
	free(syntax.contents);
	free(values->contents);
	free(values);
	return (head);
}