cdesktopenv/cde/programs/dtcm/libDtCmP/dtfns.c

995 lines
24 KiB
C

/*
* CDE - Common Desktop Environment
*
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
*
* These libraries and programs are free software; you can
* redistribute them and/or modify them under the terms of the GNU
* Lesser General Public License as published by the Free Software
* Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* These libraries and programs are distributed in the hope that
* they will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with these librararies and programs; if not, write
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
* Floor, Boston, MA 02110-1301 USA
*/
/*******************************************************************************
**
** dtfns.c
**
** $XConsortium: dtfns.c /main/3 1995/11/03 10:37:35 rswiston $
**
** RESTRICTED CONFIDENTIAL INFORMATION:
**
** The information in this document is subject to special
** restrictions in a confidential disclosure agreement between
** HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
** document outside HP, IBM, Sun, USL, SCO, or Univel without
** Sun's specific written approval. This document and all copies
** and derivative works thereof must be returned or destroyed at
** Sun's request.
**
** Copyright 1993 Sun Microsystems, Inc. All rights reserved.
**
*******************************************************************************/
/* *
* (c) Copyright 1993, 1994 Hewlett-Packard Company *
* (c) Copyright 1993, 1994 International Business Machines Corp. *
* (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
* (c) Copyright 1993, 1994 Novell, Inc. *
*/
#ifndef lint
static char sccsid[] = "@(#)dtfns.c 1.3 94/11/07 Copyr 1993 Sun Microsystems, Inc.";
#endif
/*
* Copyright 1993 Sun Microsystems, Inc. All rights reserved
*/
#ifdef FNS
#include <EUSCompat.h>
#include <unistd.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpcsvc/nis.h>
#include <rpcsvc/nislib.h>
#include <rpcsvc/ypclnt.h>
#include <dlfcn.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>
#include <fns/fns.h>
#include "debug.h"
#include "util.h"
#include "dtfns.h"
extern char *strdup(const char *);
/*
* Names found in the initial context. Used by isa_helix_name()
*
* XXX We have a bug here. If a string happens to start with
* thisuser, myorg, etc we'll recognize it as an FNS name even
* though it may not be one.
*/
static char *initial_context_names[] = {
"user:",
"thisuser",
"org:",
"site:",
"myorg",
"hostorg",
"host:",
NULL,
};
static void *libfns_handle = NULL;
static int initialized = 0;
static NS_Context_t *initial_ctx = NULL;
/*
* These are dynamically bound entry points into libfns. We dlopen()
* libfns so that cm can still run even if libfns does not exist
*/
static NS_Context_t *(*NS_Context_get_initial_p)(NS_ContextStatus_t *);
static NS_ContextStatus_t *(*NS_ContextStatus_new_p)(void);
static void (*NS_ContextStatus_delete_p)(NS_ContextStatus_t *);
static NS_Reference_t *(*NS_Context_lookup_p)(const NS_Context_t *,
const NS_CompositeName_t *,
NS_ContextStatus_t *);
static int (*NS_Context_bind_p)(const NS_Context_t *,
const NS_CompositeName_t *,
const NS_Reference_t *,
unsigned,
NS_ContextStatus_t *);
static NS_Reference_t *(*NS_Reference_new_p)(const NS_String_t *);
static void (*NS_Reference_delete_p)(const NS_Reference_t *);
static NS_String_t *(*NS_Reference_type_p)(const NS_Reference_t *);
static int (*NS_Reference_count_p)(const NS_Reference_t *);
static NS_ReferenceAddress_t *(*NS_Reference_first_p)(const NS_Reference_t *,
void **);
static NS_ReferenceAddress_t *(*NS_Reference_next_p)(const NS_Reference_t *,
void **);
static int (*NS_Reference_append_addr_p)(NS_Reference_t *,
const NS_ReferenceAddress_t *);
static int (*NS_Reference_prepend_addr_p)(NS_Reference_t *,
const NS_ReferenceAddress_t *);
static int (*NS_Reference_insert_addr_p)(NS_Reference_t *,
void **,
const NS_ReferenceAddress_t *);
static int (*NS_Reference_delete_addr_p)(NS_Reference_t *,
void **);
static void (*NS_ReferenceAddress_delete_p)(
NS_ReferenceAddress_t *);
static NS_ReferenceAddress_t *(*NS_ReferenceAddress_new_p)(const NS_String_t *,
unsigned,
const void *);
static void * (*NS_ReferenceAddress_data_p)(const NS_ReferenceAddress_t *);
static unsigned (*NS_ReferenceAddress_length_p)(const NS_ReferenceAddress_t *);
static NS_String_t *(*NS_ReferenceAddress_type_p)(const NS_ReferenceAddress_t*);
static const char * (*NS_String_cstring_p)(const NS_String_t *);
static NS_String_t * (*NS_String_from_cstring_p)(const char *);
static NS_CompositeName_t * (*NS_CompositeName_from_cstring_p)(const char *);
static int get_helix_service_name(const char *name, const char *service,
const char *service_type, char **buf);
/*
* Initialization.
*
* Load libfns (with dlopen) and bind in the entry points we use (with dlsym).
*
* We dynamically load the FNS library so that we don't have an explicit
* dependency on it. This lets us run on systems which do not have FNS
* installed
*
* Returns
* 0 FNS not available
* 1 Success
*/
int
dtfns_init(void)
{
char *libfns = FNS_LIBRARY;
int error;
if (libfns_handle != NULL) {
return 1;
}
initialized = TRUE;
libfns_handle = dlopen(libfns, RTLD_LAZY);
if (libfns_handle == NULL) {
#ifdef CM_DEBUG
char *s = dlerror();
if (s == NULL) {
DP(("Could not dlopen %s\n", libfns));
} else {
DP(("Could not dlopen %s: %s\n", libfns, s));
}
#endif
return 0;
}
NS_Context_get_initial_p = (NS_Context_t *(*)(NS_ContextStatus_t *))
dlsym(libfns_handle, "NS_Context_get_initial");
NS_ContextStatus_new_p = (NS_ContextStatus_t *(*)(void))
dlsym(libfns_handle, "NS_ContextStatus_new");
NS_ContextStatus_delete_p = (void(*)(NS_ContextStatus_t *))
dlsym(libfns_handle, "NS_ContextStatus_delete");
NS_Context_lookup_p = (NS_Reference_t *(*)(const NS_Context_t *,
const NS_CompositeName_t *,
NS_ContextStatus_t *))
dlsym(libfns_handle, "NS_Context_lookup");
NS_Context_bind_p = (int(*)(const NS_Context_t *,
const NS_CompositeName_t *,
const NS_Reference_t *,
unsigned,
NS_ContextStatus_t *))
dlsym(libfns_handle, "NS_Context_bind");
NS_Reference_new_p = (NS_Reference_t *(*)(const NS_String_t *))
dlsym(libfns_handle, "NS_Reference_new");
NS_Reference_delete_p = (void(*)(const NS_Reference_t *))
dlsym(libfns_handle, "NS_Reference_delete");;
NS_Reference_type_p = (NS_String_t *(*)(const NS_Reference_t *))
dlsym(libfns_handle, "NS_Reference_type");
NS_Reference_count_p = (int(*)(const NS_Reference_t *))
dlsym(libfns_handle, "NS_Reference_count");
NS_Reference_first_p = (NS_ReferenceAddress_t *(*)
(const NS_Reference_t *, void **))
dlsym(libfns_handle, "NS_Reference_first");
NS_Reference_next_p = (NS_ReferenceAddress_t *(*)
(const NS_Reference_t *, void **))
dlsym(libfns_handle, "NS_Reference_next");
NS_Reference_append_addr_p = (int(*)(NS_Reference_t *,
const NS_ReferenceAddress_t *))
dlsym(libfns_handle, "NS_Reference_append_addr");
NS_Reference_prepend_addr_p = (int(*)(NS_Reference_t *,
const NS_ReferenceAddress_t *))
dlsym(libfns_handle, "NS_Reference_prepend_addr");
NS_Reference_insert_addr_p = (int(*)(NS_Reference_t *,
void **,
const NS_ReferenceAddress_t *))
dlsym(libfns_handle, "NS_Reference_insert_addr");
NS_Reference_delete_addr_p = (int(*)(NS_Reference_t *, void **))
dlsym(libfns_handle, "NS_Reference_delete_addr");
NS_ReferenceAddress_delete_p = (void(*)(NS_ReferenceAddress_t *))
dlsym(libfns_handle, "NS_ReferenceAddress_delete");
NS_ReferenceAddress_new_p = (NS_ReferenceAddress_t *(*)
(const NS_String_t *, unsigned, const void *))
dlsym(libfns_handle, "NS_ReferenceAddress_new");
NS_ReferenceAddress_data_p = (void *(*)(const NS_ReferenceAddress_t *))
dlsym(libfns_handle, "NS_ReferenceAddress_data");
NS_ReferenceAddress_length_p = (unsigned(*)
(const NS_ReferenceAddress_t *))
dlsym(libfns_handle, "NS_ReferenceAddress_length");
NS_ReferenceAddress_type_p = (NS_String_t *(*)
(const NS_ReferenceAddress_t *))
dlsym(libfns_handle, "NS_ReferenceAddress_type");
NS_String_cstring_p = (const char *(*)(const NS_String_t *))
dlsym(libfns_handle, "NS_String_cstring");
NS_String_from_cstring_p = (NS_String_t * (*)(const char *))
dlsym(libfns_handle, "NS_String_from_cstring");
NS_CompositeName_from_cstring_p =(NS_CompositeName_t *(*)(const char *))
dlsym(libfns_handle, "NS_CompositeName_from_cstring");
return 1;
}
/*
* Check if FNS is available for use.
*
* You must call dfsinit() before calling this routine.
*
* First call to this routine may be costly as we get the initial context.
* Subsequent calls are very cheap.
*
* Returns
* 1 Yes, FNS is available.
* 0 No, FNS is not available.
* -1 You haven't called dtfns_init().
*/
int
dtfns_available(void)
{
static int available;
static int called;
if (called) {
return available;
}
if (libfns_handle != NULL) {
/*
* libfns has been dlopened. Now see if an FNS namespace
* is reachable by getting the initial context.
*/
if (dtfns_get_initial_ctx() == NULL) {
available = 0;
} else {
available = 1;
}
} else if (initialized) {
/* dlopen must have failed. FNS is not installed */
available = 0;
} else {
available = -1;
}
called = 1;
return available;
}
/*
* Get the initial context. This routine caches the initial context.
* The first call to this routine may be costly, be subsequent calls
* are very cheap.
*/
NS_Context_t *
dtfns_get_initial_ctx(void)
{
DP(("dtfns_get_initial_ctx: Getting initial context\n"));
if (initial_ctx == NULL) {
NS_ContextStatus_t * status;
status = (*NS_ContextStatus_new_p)();
initial_ctx = (*NS_Context_get_initial_p)(status);
(*NS_ContextStatus_delete_p)(status);
}
return initial_ctx;
}
/*
* Generate a full Helix name for a service.
*
* 'name' may be a relative Helix name. I.e.:
* smith
* smith:service
* smith:service:calendar
* In this case dtfns_service_name() will use the type, service and org
* parameters (if needed) to construct the full Helix name.
*
* 'name' may also be an absolute Helix name. I.e.:
* user:smith
* org:ssi.eng:user:smith
* user:smith:service
* In this case dtfns_service_name() will use the type and service
* parameters (if needed) to construct the full Helix name. The org
* parameter should be NULL (since the organization is already
* determined by the absolute Helix name).
*
* 'type' specifies the type of object 'name' refers to (ie "user").
*
* 'service' specifies what service is desired (ie "calendar").
*
* 'service_type' specifies the reference type of the service
* (ie SUNW_fns_calendar);
*
* 'org' is the organization name. This must be NULL if 'name' is
* an absolute Helix name. 'org' may be NULL in all other cases if the
* default organization is to be used.
*
* 'buf' is a buffer provided by the caller in which the expanded name
* is placed.
*
* 'size' is the size of 'buf'
*
*
* The string returned in buf may be used in calls to dtfns_lookup_str() and
* dtfns_lookup_ref().
*
* Returns
* -1 Name not found / Error
* 0 FNS not available
* 1 Success
*/
int
dtfns_service_name(
const char *name, /* Name to lookup */
const char *type, /* Type of object name is (ie "user") */
const char *service, /* Service name (ie "calendar") */
const char *service_type, /* Service reference type */
/* (ie "SUNW_fns_calendar"); */
const char *org, /* Org name (ie "ssi"). NULL for default org */
char *buf, /* Buffer to place name in */
const int size) /* Size of value_buf */
{
char *tmp_buf;
char *type_str;
if (libfns_handle == NULL) {
return 0;
}
if (name == NULL) {
return -1;
}
if (org != NULL && *org != '\0') {
/* Sanity check for size */
if (strlen(org) + strlen(name) > (size_t)size - 50) {
return -1;
}
/*Construct Helix name from name and organization */
sprintf(buf,"%s:%s:%s:%s:%s:%s", DTFNS_ORG_NAME,
org, type, name, DTFNS_SERVICE_NAME, service);
} else if (dtfns_isa_helix_name(name)) {
/* Helix name. Expand it to point to calendar service */
if (get_helix_service_name(name, service, service_type,
&tmp_buf) < 0) {
return -1;
}
buf[size - 1] = '\0';
strncpy(buf, tmp_buf, size - 1);
free(tmp_buf);
} else {
/* Construct Helix name from name */
sprintf(buf,"%s:%s:%s:%s", type,
name, DTFNS_SERVICE_NAME, service);
}
return 1;
}
/*
* Return TRUE if 'name' is an absolute Helix name
*/
int
dtfns_isa_helix_name(const char *name)
{
int n, len;
char **p;
for (p = initial_context_names; *p != NULL; p++) {
len = strlen(*p);
if (strncmp(name, *p, len) == 0) {
return TRUE;
}
}
return FALSE;
}
/*
* Get the org name for "myorg" (ie ssi.eng)
*/
void
dtfns_myorg_name(char *buf, int len)
{
char *__nis_local_root();
static char *myorg_name;
char *principal_name;
char *host_domain;
char *root_domain;
char *pd = NULL;
char *myorg_p, *root_p;
if (myorg_name == NULL) {
principal_name = nis_local_principal();
host_domain = nis_local_directory();
root_domain = __nis_local_root();
if (principal_name) {
/* Get the domain this principal is in */
pd = nis_domain_of(principal_name);
if (pd && *pd == '.') {
pd = NULL;
}
}
/* If no domain for the principal, use the one for the host */
myorg_name = strdup(pd ? pd : (host_domain ? host_domain : ""));
/*
* We want to strip the root domain name off of the
* end of the myorg name. Set pointers to the end
* of each name
*/
myorg_p = myorg_name + strlen(myorg_name) - 1;
root_p = root_domain + strlen(root_domain) - 1;
while (tolower(*myorg_p) == tolower(*root_p)) {
if (root_p == root_domain) {
/* Matched all of root domain name. Truncate */
if (myorg_p != myorg_name) {
*--myorg_p = '\0';
}
break;
} else if (myorg_p == myorg_name) {
break;
}
--myorg_p;
--root_p;
}
}
if (myorg_name != NULL) {
buf[len - 1] = '\0';
strncpy(buf, myorg_name, len - 1);
}
return;
}
/*
* Return the string value bound to an absolute Helix name
*
* Returns
* -1 Error
* 0 FNS not available
* 1 Success
*/
int
dtfns_lookup_str(
const char *name, /* Absolute Helix name */
char *types[], /* Type of data to get */
char *dbuf, /* Buffer to place data value in */
int dsize, /* Size of dbuf */
char *tbuf, /* Buffer to place address type in */
int tsize) /* Size of tbuf */
{
NS_Reference_t * ref;
const NS_ReferenceAddress_t * addr;
void *iter_pos;
if (libfns_handle == NULL) {
return 0;
}
/* Get the reference from the name */
if ((ref = dtfns_lookup_ref(name)) == NULL) {
return -1;
}
/* Get the address that matches at least one of the specified types */
if ((addr = dtfns_addr_from_ref(ref, types, &iter_pos)) == NULL) {
(*NS_Reference_delete_p)(ref);
return -1;
}
(*NS_Reference_delete_p)(ref);
/* Return data bound to that address */
return dtfns_str_from_addr(addr, dbuf, dsize, tbuf, tsize);
}
/*
*
* Bind a string to a name.
*
* name Absolute Helix name to bind string to
*
* ref_type Reference type. We need this to create
* the reference if it does not already exist.
*
* types Array of address types. This routine looks for
* the address that matches at least one of these
* types. The first type is used when the new
* string is bound.
*
* new_str String to bind to name
*
* Returns
* -1 Error
* 0 FNS not available
* 1 Success
*/
int
dtfns_bind_str(
const char *name, /* Absolute Helix name */
const char *ref_type, /* Reference type */
char *types[], /* Address type of data to operate on */
const char *new_str /* String to bind to name */
)
{
NS_Reference_t *ref = NULL;
const NS_ReferenceAddress_t *addr = NULL;
NS_ReferenceAddress_t *new_addr = NULL;
NS_CompositeName_t *comp_name;
NS_ContextStatus_t *status = NULL;
NS_Context_t *ctx = NULL;
NS_String_t *nstr;
void *iter_pos = NULL;
char buf[256];
int rcode = -1;
if (libfns_handle == NULL) {
return 0;
}
/* Get the reference from the name */
if ((ref = dtfns_lookup_ref(name)) != NULL) {
/*
* A value is already bound to this name.
* Get the address that matches at least one of
* the specified types
*/
addr = dtfns_addr_from_ref(ref, types, &iter_pos);
if (addr != NULL) {
/* Get string bound to that address */
*buf = '\0';
dtfns_str_from_addr(addr, buf, sizeof(buf), NULL, 0);
/* Are we changing the string? */
if (strcmp(buf, new_str) == 0) {
/* Bound value is the same as new value */
rcode = 1;
goto EXIT;
} else {
/* Delete old address string */
(*NS_Reference_delete_addr_p)(ref, &iter_pos);
}
}
} else {
/* Nothing bound to name. Create an empty reference */
nstr = (*NS_String_from_cstring_p)(ref_type);
ref = (*NS_Reference_new_p)(nstr);
iter_pos = NULL;
}
/* Create new address */
if ((new_addr = dtfns_create_str_addr(new_str, types[0])) == NULL) {
goto EXIT;
}
/* Insert new address into reference */
if (dtfns_insert_addr(ref, &iter_pos, new_addr) < 1) {
goto EXIT;
}
/* Bind reference into name space */
if ((ctx = dtfns_get_initial_ctx()) == NULL) {
goto EXIT;
}
status = (*NS_ContextStatus_new_p)();
comp_name = (*NS_CompositeName_from_cstring_p)(name);
if ((*NS_Context_bind_p)(ctx, comp_name, ref, 0, status) < 1) {
goto EXIT;
}
rcode = 1;
EXIT:
/* Clean up and return */
if (new_addr != NULL) (*NS_ReferenceAddress_delete_p)(new_addr);
if (ref != NULL) (*NS_Reference_delete_p)(ref);
if (status != NULL) (*NS_ContextStatus_delete_p)(status);
return rcode;
}
/*
* Return the reference bound to an absolute Helix name
*
* Returns
* NULL Error
* NS_Reference_t * for reference
*/
NS_Reference_t *
dtfns_lookup_ref(
const char *name)/* Absolute Helix name to lookup */
{
NS_Reference_t * ref = NULL;
NS_ContextStatus_t * status = NULL;
NS_CompositeName_t * comp_name = NULL;
NS_Context_t * ctx;
if (libfns_handle == NULL) {
return NULL;
}
status = (*NS_ContextStatus_new_p)();
if ((ctx = dtfns_get_initial_ctx()) != NULL) {
/* Lookup the Helix name specified by "name" */
comp_name = (*NS_CompositeName_from_cstring_p)(name);
ref = (*NS_Context_lookup_p)(ctx, comp_name, status);
}
(*NS_ContextStatus_delete_p)(status);
return ref;
}
/*
* Takes a Helix name and converts it to a full name for a service.
* I.e. if service is "calendar":
*
* name buf
* org:ss-eng:user:dipol --> org:ss-eng:user:dipol:service:calendar
* org:ss-eng --> org:ss-eng:service:calendar
* org:ss-eng:service: --> org:ss-eng:service:calendar
*
* Returns
* -1 Error. buf not set
* 0 name already points to the service
* buf is a duplicate of name.
* 1 name resolved. buf is set. Caller
* is responsible for freeing memory.
*/
static int
get_helix_service_name(
const char *name,
const char *service,
const char *service_type,
char **buf)
{
int n;
char *tmp_name;
NS_Reference_t *ref;
NS_String_t *nstr;
const char *type;
char *p;
n = strlen(name);
tmp_name = strdup(name);
/* Remove trailing : if there is one */
if (tmp_name[n - 1] == ':') {
tmp_name[n - 1] = '\0';
n--;
}
/* Get reference and extract reference type */
if ((ref = dtfns_lookup_ref(tmp_name)) == NULL) {
return -1;
}
nstr = (*NS_Reference_type_p)(ref);
type = (*NS_String_cstring_p)(nstr);
(*NS_Reference_delete_p)(ref);
/* If name is already bound to a calendar service then we are done */
if (strcmp(type, service_type) == 0) {
*buf = strdup(name);
return 0;
}
if ((p = strrchr(tmp_name, ':')) != NULL) {
p++;
}
/*
* If name is a service context or the "service" null context
* then we want to append ":calendar"
*/
if (strcmp(type, DTFNS_SERVICE_CONTEXT_TYPE) == 0 ||
(strcmp(type, DTFNS_NULL_CONTEXT_TYPE) == 0 && p != NULL &&
strcmp(p, DTFNS_SERVICE_NAME) == 0)) {
*buf = (char *)malloc(n + strlen(service) + 2);
if (*buf == NULL) {
return -1;
}
strcpy(*buf, tmp_name);
strcat(*buf, ":");
strcat(*buf, service);
return 1;
} else {
/* Append ":service:calendar" */
*buf = (char *)malloc(n +
strlen(DTFNS_SERVICE_NAME) +
strlen(service) + 3);
sprintf(*buf, "%s:%s:%s", tmp_name,
DTFNS_SERVICE_NAME, service);
return 1;
}
}
/*
* Get an FNS Address from a Reference.
*
* ref The Reference to get the address from
*
* types NULL terminated array of one or more type strings.
* This routine returns the first address that matches
* a type specified in this array. NULL to just
* get the first address.
*
* iter_pos Updated to point after retrieved address.
*
* Returns
* Pointer to the found address
* NULL if no address is found
*
*/
const NS_ReferenceAddress_t *
dtfns_addr_from_ref(
const NS_Reference_t *ref, /* Reference to get addr from */
char *types[], /* Types of addrs to get */
void **iter_pos /* Returned pos where addr was found */
)
{
const NS_ReferenceAddress_t *addr;
char type[128];
char **p;
if (libfns_handle == NULL) {
return 0;
}
addr = (*NS_Reference_first_p)(ref, iter_pos);
if (types == NULL) {
return addr;
}
while (addr != NULL) {
/* Get the type, and see if it is one we want */
dtfns_str_from_addr(addr, NULL, 0, type, sizeof(type));
for (p = types; *p != NULL && strcmp(*p, type) != 0; *p++)
;
if (*p != NULL) {
/* Found it! */
break;
} else {
/* Get next address */
addr = (*NS_Reference_next_p)(ref, iter_pos);
}
}
return addr;
}
/*
* Get the string and type out of an Address
*
* Returns
* -1 Error
* 0 FNS not available
* 1 Success
*/
int
dtfns_str_from_addr(
const NS_ReferenceAddress_t *addr, /* Addr to get string from */
char *dbuf, /* Buf to hold string data */
int dbuf_size, /* Size of dbuf */
char *tbuf, /* Buf to hold string type */
int tbuf_size /* size of tbuf */
)
{
XDR xdr;
char *s = NULL;
NS_String_t *nstr;
const char *cs;
if (libfns_handle == NULL) {
return 0;
}
if (dbuf != NULL) {
/* Convert data from XDR to a string */
xdrmem_create(&xdr,
(caddr_t)(*NS_ReferenceAddress_data_p)(addr),
(*NS_ReferenceAddress_length_p)(addr), XDR_DECODE);
if (xdr_string(&xdr, &s, ~0) == FALSE) {
return -1;
}
dbuf[dbuf_size - 1] = '\0';
strncpy(dbuf, s, dbuf_size - 1);
free(s);
}
if (tbuf != NULL) {
tbuf[tbuf_size - 1] = '\0';
nstr = (*NS_ReferenceAddress_type_p)(addr);
cs = (*NS_String_cstring_p)(nstr);
strncpy(tbuf, cs, tbuf_size - 1);
}
return 1;
}
/*
* Create an Address of type "type" for the string specified by "data"
*
* Returns
* A new address contianing the specified data
* NULL on an error
*/
NS_ReferenceAddress_t *
dtfns_create_str_addr(
const char *data,
const char *type
)
{
XDR xdr;
u_char buf[1024];
NS_String_t *nstring;
if (libfns_handle == NULL) {
return NULL;
}
xdrmem_create(&xdr, (caddr_t)buf, sizeof(buf), XDR_ENCODE);
if (xdr_string(&xdr, (char**)&data, ~0) == FALSE) {
return NULL;
}
nstring = (*NS_String_from_cstring_p)(type);
return (*NS_ReferenceAddress_new_p)(nstring, xdr_getpos(&xdr), buf);
}
/*
* Add an address to a reference at the location specified by iter_pos.
* The address is inserted before iter_pos.
* If *iter_pos is NULL then put the address in the first slot.
*
* Returns
* -1 Error
* 0 FNS not available
* 1 Success
*/
int
dtfns_insert_addr(
NS_Reference_t *ref,
void **iter_pos,
const NS_ReferenceAddress_t *addr
)
{
if (libfns_handle == NULL) {
return 0;
}
if (*iter_pos == NULL) {
if ((*NS_Reference_prepend_addr_p)(ref, addr) < 1)
return -1;
} else {
if ((*NS_Reference_insert_addr_p)(ref, iter_pos, addr) < 1)
return -1;
}
return 1;
}
/*
* Delete the Address at position "iter_pos" from a Reference
*
* Returns
* -1 Error
* 0 FNS not available
* 1 Success
*/
int
dtfns_delete_addr(
NS_Reference_t *ref,
void **iter_pos
)
{
if (libfns_handle == NULL) {
return 0;
}
(*NS_Reference_delete_addr_p)(ref, iter_pos);
return 1;
}
#endif /* FNS */