Federated Naming Service Programming Guide

Namespace Browser Example

Figure 3-1 illustrates the XFN APIs that are used by the browser application.

Figure 3-1 Diagram of fnbrowse Program

Graphic

The first example is a browser that lists all names that it finds in the namespace. When the program is invoked, the browser is set at the initial context or the composite name given on the command line.

See "Commands" and "Sample Output".


Example 3-1 fnbrowse Source


/*
 * fnbrowse.c -- FNS namespace browser.
 *
 * To keep this example program relatively short,
 * limited error checking is done.
 */
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xfn/xfn.h>
 
 
#define LINELEN 128    /* maximum length of input line */
 
typedef enum {CMD_DOWN, CMD_UP, CMD_LIST, CMD_SHOW, CMD_QUIT} command;
 
static FN_status_t *status;
static unsigned 	int auth = 0; /* non-authoritative */
 
 
/* Lookup a context named relative to the initial context. */
FN_ctx_t *lookup(const FN_composite_name_t *name);
 
/* Set the browser's focus to the given context. */
void browse(FN_ctx_t *ctx);
 
/* Set the browser's focus to a subcontext of the given context. */
void cmd_down(FN_ctx_t *ctx, const FN_composite_name_t *child);
 
/* Print the names bound within a context. */
void cmd_list(FN_ctx_t *ctx);
 
/*
 * Print a description of the reference bound to "child" in the
 * given context or, if "child" is the empty string, the reference
 * of the context itself.
 */
void cmd_show(FN_ctx_t *ctx, const FN_composite_name_t *child);
 
/*
 * Read and parse the next command typed by the user.  If the
 * command has an argument, set *argp to point to the argument.
 */
command read_command(FN_string_t **argp);
 
/* Print an error message, and the description associated
 * with "status". 
 */
void error(const char *msg);
 
 
int
main(int argc, char *argv[])
{
	    unsigned char	*target;
 
	    switch (argc) {
    case 1:
        target = (unsigned char *)"";
        break;
    case 2:
        target = (unsigned char *)argv[1];
        break;
    default:
        fprintf(stderr, "Usage: %s [<composite_name>]\n",
             argv[0]);
        return (1);
	}
 
    status = fn_status_create();
 
    browse(lookup(fn_composite_name_from_str(target)));
    return (0);
}
 
 
FN_ctx_t *
lookup(const FN_composite_name_t *name)
{
    FN_ctx_t	*ctx;
    FN_ref_t	*ref;
 
    ctx = fn_ctx_handle_from_initial(auth, status);
    if (ctx == NULL) {
       error("Could not construct initial context");
       exit(1);
    }
    if (fn_composite_name_is_empty(name)) {
        return (ctx);
    }
    ref = fn_ctx_lookup(ctx, name, status);
    fn_ctx_handle_destroy(ctx);
    if (ref == NULL) {
       error("Lookup failed");
       exit(1);
    }
    ctx = fn_ctx_handle_from_ref(ref, auth, status);
    fn_ref_destroy(ref);
    if (ctx == NULL) {
       error("Could not construct context handle");
       exit(1);
    }
    return (ctx);
}
 
 
void
browse(FN_ctx_t *ctx)
{
  FN_string_t		*arg;
  FN_composite_name_t	*child;
 
  while (1) {
     switch (read_command(&arg)) {
     case CMD_DOWN:
        child = fn_composite_name_from_string(arg);
        fn_string_destroy(arg);
			  cmd_down(ctx, child);
        fn_composite_name_destroy(child);
        break;
     case CMD_UP:
        return;
     case CMD_LIST:
        cmd_list(ctx);
        break;
     case CMD_SHOW:
        child = fn_composite_name_from_string(arg);
        fn_string_destroy(arg);
        cmd_show(ctx, child);
        fn_composite_name_destroy(child);
        break;
     case CMD_QUIT:
        exit(0);
     }
   }
}
 
 
void
cmd_down(FN_ctx_t *ctx, const FN_composite_name_t *child)
{
  FN_ref_t	*ref;
  FN_ctx_t	*subctx;
 
  ref = fn_ctx_lookup(ctx, child, status);
  if (ref == NULL) {
      error("Lookup failed");
      return;
  }
  subctx = fn_ctx_handle_from_ref(ref, auth, status);
  fn_ref_destroy(ref);
	  if (subctx == NULL) {
      error("Could not construct context handle");
      return;
  }
  browse(subctx);
  fn_ctx_handle_destroy(subctx);
}
 
 
void
cmd_list(FN_ctx_t *ctx)
{
  FN_string_t		*empty_string = fn_string_create();
  FN_composite_name_t	*empty_name;
  FN_namelist_t		*children;
  FN_string_t		*child;
  unsigned intstatcode;
  int  has_children = 0;
 
  empty_name = fn_composite_name_from_string(empty_string);
  fn_string_destroy(empty_string);
 
  children = fn_ctx_list_names(ctx, empty_name, status);
  fn_composite_name_destroy(empty_name);
 
  if (children == NULL) {
      error("Could not list names");
      return;
	}
  while ((child = fn_namelist_next(children, status))
    != NULL) {
    has_children = 1;
    printf("%s  ", fn_string_str(child, &statcode));
    fn_string_destroy(child);
  }
  if (has_children) {
      printf("\n");
  }
  fn_namelist_destroy(children);
}
 
 
void
cmd_show(FN_ctx_t *ctx, const FN_composite_name_t *child)
{
    FN_string_t	*desc;
    FN_ref_t	*ref;
    unsigned int	statcode;
 
    ref = fn_ctx_lookup(ctx, child, status);
    if (ref == NULL) {
        error("Lookup failed");
        return;
    }
 
    desc = fn_ref_description(ref, 2, NULL);
    fn_ref_destroy(ref);
    if (desc != NULL) {
        printf("%s", fn_string_str(desc, &statcode));
        fn_string_destroy(desc);
    } else {
        printf("[No description]\n");
	    }
}
 
 
command
read_command(FN_string_t **argp)
{
     char	buf[LINELEN + 1];
     char  *cmd;
     char  *child;
 
     while (printf("\n> "), fflush(stdout), gets(buf) != NULL) {
        cmd = strtok(buf, " \t");
        if (cmd == NULL) {
            continue;
		     }
        if (strcmp(cmd, "down") == 0) {
           child = strtok(NULL, " \t");
           if (child != NULL) {
              *argp =
                  fn_string_from_str((unsigned char *)child);
              return (CMD_DOWN);
           }
        }
        if (strcmp(cmd, "up") == 0) {
           return (CMD_UP);
        }
        if (strcmp(cmd, "list") == 0) {
           return (CMD_LIST);
        }
        if (strcmp(cmd, "show") == 0) {
           child = strtok(NULL, " \t");
           *argp = (child != NULL)
               ? fn_string_from_str((unsigned char *)child)
               : fn_string_create();
           return (CMD_SHOW);
        }
        if (strcmp(cmd, "quit") == 0) {
           return (CMD_QUIT);
		    }
       fprintf(stderr, "Valid commands are:  "
           "down <child>, up, list, show [<child>], quit\n");
    }
    return (CMD_QUIT);	/* EOF */
}
 
 
void
error(const char *msg)
{
    FN_string_t	*reason;
    unsigned int	statcode;
 
    fprintf(stderr, "%s", msg);
    reason = fn_status_description(status, 0, NULL);
    if (reason != NULL) {
        fprintf(stderr, ": %s",
            (const char *)fn_string_str(reason, &statcode));
        fn_string_destroy(reason);
    }
    fprintf(stderr, "\n");
}

Compiling and Executing Browser Example

To compile Example 3-1, type:


% cc -o fnbrowse fnbrowse.c -lxfn

To browse the namespace starting from the initial context, the program is invoked as:


% fnbrowse

Or to browse a composite name and its descendents, type:


% fnbrowse composite_name

Commands

The commands supported by the fnbrowse program are summarized in Table 3-1.

Table 3-1 Namespace Browser Commands

Command 

Usage 

down child

Sets the browser at the subcontext of the child 

up

Sets the browser at one level higher than the current context 

list

Lists the names bound within the current context 

show

Prints the reference of the current context 

show child

Prints the reference of the current context's child 

quit

Exits the browser 

Sample Output

Sample output for navigating the entire namespace is displayed here.

Note the following:


% fnbrowse
> list
_myorgunit  ...  _myself  thishost  myself  _orgunit  _host 
_thisens  myens  thisens  org  orgunit  thisuser  _thishost 
myorgunit  _user  thisorgunit  host  _thisorgunit  _myens  user

Navigating the namespace is accomplished with the up and down commands. In the following output, the down command brings the focus of the browser to the enterprise root of the namespace, thisens (can also be myens). The show command displays information about the reference and address type for thisens.


> down thisens
> show
Reference type: onc_fn_enterprise
Address type: on_fn_nisplus
  length: 20
  context type: enterprise root
  representation: normal
  version: 0
  internal name: eng.wiz.com
> up
> down thisorgunit

Continuing with the example, this list command shows the contexts for thisorgunit.


> list 
service  _fs  _host  _service  _site  site  _user  host  fs  user 
 
> down usr
Lookup failed: Name Not Found: 'usr'
 
> down service
> list
printer
 
> down printer 

The list command shows the printer names that are bound in the printer context. The show command displays the reference for the child, colorful.


> list 
celeste  _default  color  colorful  quartz  nuttree  puffin 
 
> show colorful
printer   
Reference type: onc_printers
Address type: onc_printers_bsdaddr
  length: 12
  data: 0x00 0x00 0x00 0x08 0x62 0x6c 0x61 0x63 0x6b 0x63 
....blackc 0x61 0x74 at
> down colorful
Could not construct context handle: No Supported Address
> quit
%