2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /*******************************************************************************
27 ** $XConsortium: dtfns.c /main/3 1995/11/03 10:37:35 rswiston $
29 ** RESTRICTED CONFIDENTIAL INFORMATION:
31 ** The information in this document is subject to special
32 ** restrictions in a confidential disclosure agreement between
33 ** HP, IBM, Sun, USL, SCO and Univel. Do not distribute this
34 ** document outside HP, IBM, Sun, USL, SCO, or Univel without
35 ** Sun's specific written approval. This document and all copies
36 ** and derivative works thereof must be returned or destroyed at
39 ** Copyright 1993 Sun Microsystems, Inc. All rights reserved.
41 *******************************************************************************/
44 * (c) Copyright 1993, 1994 Hewlett-Packard Company *
45 * (c) Copyright 1993, 1994 International Business Machines Corp. *
46 * (c) Copyright 1993, 1994 Sun Microsystems, Inc. *
47 * (c) Copyright 1993, 1994 Novell, Inc. *
52 static char sccsid[] = "@(#)dtfns.c 1.3 94/11/07 Copyr 1993 Sun Microsystems, Inc.";
56 * Copyright 1993 Sun Microsystems, Inc. All rights reserved
61 #include <EUSCompat.h>
65 #include <sys/types.h>
71 #include <rpcsvc/nis.h>
72 #include <rpcsvc/nislib.h>
73 #include <rpcsvc/ypclnt.h>
85 extern char *strdup(const char *);
88 * Names found in the initial context. Used by isa_helix_name()
90 * XXX We have a bug here. If a string happens to start with
91 * thisuser, myorg, etc we'll recognize it as an FNS name even
92 * though it may not be one.
94 static char *initial_context_names[] = {
104 static void *libfns_handle = NULL;
105 static int initialized = 0;
106 static NS_Context_t *initial_ctx = NULL;
109 * These are dynamically bound entry points into libfns. We dlopen()
110 * libfns so that cm can still run even if libfns does not exist
112 static NS_Context_t *(*NS_Context_get_initial_p)(NS_ContextStatus_t *);
113 static NS_ContextStatus_t *(*NS_ContextStatus_new_p)(void);
114 static void (*NS_ContextStatus_delete_p)(NS_ContextStatus_t *);
115 static NS_Reference_t *(*NS_Context_lookup_p)(const NS_Context_t *,
116 const NS_CompositeName_t *,
117 NS_ContextStatus_t *);
118 static int (*NS_Context_bind_p)(const NS_Context_t *,
119 const NS_CompositeName_t *,
120 const NS_Reference_t *,
122 NS_ContextStatus_t *);
124 static NS_Reference_t *(*NS_Reference_new_p)(const NS_String_t *);
125 static void (*NS_Reference_delete_p)(const NS_Reference_t *);
126 static NS_String_t *(*NS_Reference_type_p)(const NS_Reference_t *);
127 static int (*NS_Reference_count_p)(const NS_Reference_t *);
128 static NS_ReferenceAddress_t *(*NS_Reference_first_p)(const NS_Reference_t *,
130 static NS_ReferenceAddress_t *(*NS_Reference_next_p)(const NS_Reference_t *,
132 static int (*NS_Reference_append_addr_p)(NS_Reference_t *,
133 const NS_ReferenceAddress_t *);
134 static int (*NS_Reference_prepend_addr_p)(NS_Reference_t *,
135 const NS_ReferenceAddress_t *);
136 static int (*NS_Reference_insert_addr_p)(NS_Reference_t *,
138 const NS_ReferenceAddress_t *);
139 static int (*NS_Reference_delete_addr_p)(NS_Reference_t *,
141 static void (*NS_ReferenceAddress_delete_p)(
142 NS_ReferenceAddress_t *);
144 static NS_ReferenceAddress_t *(*NS_ReferenceAddress_new_p)(const NS_String_t *,
147 static void * (*NS_ReferenceAddress_data_p)(const NS_ReferenceAddress_t *);
148 static unsigned (*NS_ReferenceAddress_length_p)(const NS_ReferenceAddress_t *);
149 static NS_String_t *(*NS_ReferenceAddress_type_p)(const NS_ReferenceAddress_t*);
152 static const char * (*NS_String_cstring_p)(const NS_String_t *);
153 static NS_String_t * (*NS_String_from_cstring_p)(const char *);
154 static NS_CompositeName_t * (*NS_CompositeName_from_cstring_p)(const char *);
157 static int get_helix_service_name(const char *name, const char *service,
158 const char *service_type, char **buf);
162 * Load libfns (with dlopen) and bind in the entry points we use (with dlsym).
164 * We dynamically load the FNS library so that we don't have an explicit
165 * dependency on it. This lets us run on systems which do not have FNS
169 * 0 FNS not available
176 char *libfns = FNS_LIBRARY;
179 if (libfns_handle != NULL) {
185 libfns_handle = dlopen(libfns, RTLD_LAZY);
186 if (libfns_handle == NULL) {
190 DP(("Could not dlopen %s\n", libfns));
192 DP(("Could not dlopen %s: %s\n", libfns, s));
198 NS_Context_get_initial_p = (NS_Context_t *(*)(NS_ContextStatus_t *))
199 dlsym(libfns_handle, "NS_Context_get_initial");
201 NS_ContextStatus_new_p = (NS_ContextStatus_t *(*)(void))
202 dlsym(libfns_handle, "NS_ContextStatus_new");
203 NS_ContextStatus_delete_p = (void(*)(NS_ContextStatus_t *))
204 dlsym(libfns_handle, "NS_ContextStatus_delete");
206 NS_Context_lookup_p = (NS_Reference_t *(*)(const NS_Context_t *,
207 const NS_CompositeName_t *,
208 NS_ContextStatus_t *))
209 dlsym(libfns_handle, "NS_Context_lookup");
211 NS_Context_bind_p = (int(*)(const NS_Context_t *,
212 const NS_CompositeName_t *,
213 const NS_Reference_t *,
215 NS_ContextStatus_t *))
216 dlsym(libfns_handle, "NS_Context_bind");
218 NS_Reference_new_p = (NS_Reference_t *(*)(const NS_String_t *))
219 dlsym(libfns_handle, "NS_Reference_new");
220 NS_Reference_delete_p = (void(*)(const NS_Reference_t *))
221 dlsym(libfns_handle, "NS_Reference_delete");;
223 NS_Reference_type_p = (NS_String_t *(*)(const NS_Reference_t *))
224 dlsym(libfns_handle, "NS_Reference_type");
226 NS_Reference_count_p = (int(*)(const NS_Reference_t *))
227 dlsym(libfns_handle, "NS_Reference_count");
229 NS_Reference_first_p = (NS_ReferenceAddress_t *(*)
230 (const NS_Reference_t *, void **))
231 dlsym(libfns_handle, "NS_Reference_first");
233 NS_Reference_next_p = (NS_ReferenceAddress_t *(*)
234 (const NS_Reference_t *, void **))
235 dlsym(libfns_handle, "NS_Reference_next");
237 NS_Reference_append_addr_p = (int(*)(NS_Reference_t *,
238 const NS_ReferenceAddress_t *))
239 dlsym(libfns_handle, "NS_Reference_append_addr");
241 NS_Reference_prepend_addr_p = (int(*)(NS_Reference_t *,
242 const NS_ReferenceAddress_t *))
243 dlsym(libfns_handle, "NS_Reference_prepend_addr");
245 NS_Reference_insert_addr_p = (int(*)(NS_Reference_t *,
247 const NS_ReferenceAddress_t *))
248 dlsym(libfns_handle, "NS_Reference_insert_addr");
250 NS_Reference_delete_addr_p = (int(*)(NS_Reference_t *, void **))
251 dlsym(libfns_handle, "NS_Reference_delete_addr");
253 NS_ReferenceAddress_delete_p = (void(*)(NS_ReferenceAddress_t *))
254 dlsym(libfns_handle, "NS_ReferenceAddress_delete");
257 NS_ReferenceAddress_new_p = (NS_ReferenceAddress_t *(*)
258 (const NS_String_t *, unsigned, const void *))
259 dlsym(libfns_handle, "NS_ReferenceAddress_new");
261 NS_ReferenceAddress_data_p = (void *(*)(const NS_ReferenceAddress_t *))
262 dlsym(libfns_handle, "NS_ReferenceAddress_data");
264 NS_ReferenceAddress_length_p = (unsigned(*)
265 (const NS_ReferenceAddress_t *))
266 dlsym(libfns_handle, "NS_ReferenceAddress_length");
268 NS_ReferenceAddress_type_p = (NS_String_t *(*)
269 (const NS_ReferenceAddress_t *))
270 dlsym(libfns_handle, "NS_ReferenceAddress_type");
272 NS_String_cstring_p = (const char *(*)(const NS_String_t *))
273 dlsym(libfns_handle, "NS_String_cstring");
275 NS_String_from_cstring_p = (NS_String_t * (*)(const char *))
276 dlsym(libfns_handle, "NS_String_from_cstring");
278 NS_CompositeName_from_cstring_p =(NS_CompositeName_t *(*)(const char *))
279 dlsym(libfns_handle, "NS_CompositeName_from_cstring");
285 * Check if FNS is available for use.
287 * You must call dfsinit() before calling this routine.
289 * First call to this routine may be costly as we get the initial context.
290 * Subsequent calls are very cheap.
293 * 1 Yes, FNS is available.
294 * 0 No, FNS is not available.
295 * -1 You haven't called dtfns_init().
298 dtfns_available(void)
301 static int available;
308 if (libfns_handle != NULL) {
311 * libfns has been dlopened. Now see if an FNS namespace
312 * is reachable by getting the initial context.
314 if (dtfns_get_initial_ctx() == NULL) {
319 } else if (initialized) {
320 /* dlopen must have failed. FNS is not installed */
331 * Get the initial context. This routine caches the initial context.
332 * The first call to this routine may be costly, be subsequent calls
336 dtfns_get_initial_ctx(void)
339 DP(("dtfns_get_initial_ctx: Getting initial context\n"));
341 if (initial_ctx == NULL) {
342 NS_ContextStatus_t * status;
344 status = (*NS_ContextStatus_new_p)();
345 initial_ctx = (*NS_Context_get_initial_p)(status);
346 (*NS_ContextStatus_delete_p)(status);
353 * Generate a full Helix name for a service.
355 * 'name' may be a relative Helix name. I.e.:
358 * smith:service:calendar
359 * In this case dtfns_service_name() will use the type, service and org
360 * parameters (if needed) to construct the full Helix name.
362 * 'name' may also be an absolute Helix name. I.e.:
364 * org:ssi.eng:user:smith
366 * In this case dtfns_service_name() will use the type and service
367 * parameters (if needed) to construct the full Helix name. The org
368 * parameter should be NULL (since the organization is already
369 * determined by the absolute Helix name).
371 * 'type' specifies the type of object 'name' refers to (ie "user").
373 * 'service' specifies what service is desired (ie "calendar").
375 * 'service_type' specifies the reference type of the service
376 * (ie SUNW_fns_calendar);
378 * 'org' is the organization name. This must be NULL if 'name' is
379 * an absolute Helix name. 'org' may be NULL in all other cases if the
380 * default organization is to be used.
382 * 'buf' is a buffer provided by the caller in which the expanded name
385 * 'size' is the size of 'buf'
388 * The string returned in buf may be used in calls to dtfns_lookup_str() and
389 * dtfns_lookup_ref().
392 * -1 Name not found / Error
393 * 0 FNS not available
398 const char *name, /* Name to lookup */
399 const char *type, /* Type of object name is (ie "user") */
400 const char *service, /* Service name (ie "calendar") */
401 const char *service_type, /* Service reference type */
402 /* (ie "SUNW_fns_calendar"); */
403 const char *org, /* Org name (ie "ssi"). NULL for default org */
404 char *buf, /* Buffer to place name in */
405 const int size) /* Size of value_buf */
411 if (libfns_handle == NULL) {
419 if (org != NULL && *org != '\0') {
420 /* Sanity check for size */
421 if (strlen(org) + strlen(name) > (size_t)size - 50) {
425 /*Construct Helix name from name and organization */
426 sprintf(buf,"%s:%s:%s:%s:%s:%s", DTFNS_ORG_NAME,
427 org, type, name, DTFNS_SERVICE_NAME, service);
428 } else if (dtfns_isa_helix_name(name)) {
429 /* Helix name. Expand it to point to calendar service */
430 if (get_helix_service_name(name, service, service_type,
434 buf[size - 1] = '\0';
435 strncpy(buf, tmp_buf, size - 1);
439 /* Construct Helix name from name */
440 sprintf(buf,"%s:%s:%s:%s", type,
441 name, DTFNS_SERVICE_NAME, service);
448 * Return TRUE if 'name' is an absolute Helix name
451 dtfns_isa_helix_name(const char *name)
457 for (p = initial_context_names; *p != NULL; p++) {
459 if (strncmp(name, *p, len) == 0) {
468 * Get the org name for "myorg" (ie ssi.eng)
471 dtfns_myorg_name(char *buf, int len)
474 char *__nis_local_root();
475 static char *myorg_name;
476 char *principal_name;
480 char *myorg_p, *root_p;
482 if (myorg_name == NULL) {
483 principal_name = nis_local_principal();
484 host_domain = nis_local_directory();
485 root_domain = __nis_local_root();
487 if (principal_name) {
488 /* Get the domain this principal is in */
489 pd = nis_domain_of(principal_name);
490 if (pd && *pd == '.') {
495 /* If no domain for the principal, use the one for the host */
496 myorg_name = strdup(pd ? pd : (host_domain ? host_domain : ""));
499 * We want to strip the root domain name off of the
500 * end of the myorg name. Set pointers to the end
503 myorg_p = myorg_name + strlen(myorg_name) - 1;
504 root_p = root_domain + strlen(root_domain) - 1;
506 while (tolower(*myorg_p) == tolower(*root_p)) {
507 if (root_p == root_domain) {
508 /* Matched all of root domain name. Truncate */
509 if (myorg_p != myorg_name) {
513 } else if (myorg_p == myorg_name) {
521 if (myorg_name != NULL) {
523 strncpy(buf, myorg_name, len - 1);
530 * Return the string value bound to an absolute Helix name
534 * 0 FNS not available
539 const char *name, /* Absolute Helix name */
540 char *types[], /* Type of data to get */
541 char *dbuf, /* Buffer to place data value in */
542 int dsize, /* Size of dbuf */
543 char *tbuf, /* Buffer to place address type in */
544 int tsize) /* Size of tbuf */
547 NS_Reference_t * ref;
548 const NS_ReferenceAddress_t * addr;
551 if (libfns_handle == NULL) {
555 /* Get the reference from the name */
556 if ((ref = dtfns_lookup_ref(name)) == NULL) {
560 /* Get the address that matches at least one of the specified types */
561 if ((addr = dtfns_addr_from_ref(ref, types, &iter_pos)) == NULL) {
562 (*NS_Reference_delete_p)(ref);
566 (*NS_Reference_delete_p)(ref);
568 /* Return data bound to that address */
569 return dtfns_str_from_addr(addr, dbuf, dsize, tbuf, tsize);
574 * Bind a string to a name.
576 * name Absolute Helix name to bind string to
578 * ref_type Reference type. We need this to create
579 * the reference if it does not already exist.
581 * types Array of address types. This routine looks for
582 * the address that matches at least one of these
583 * types. The first type is used when the new
586 * new_str String to bind to name
590 * 0 FNS not available
595 const char *name, /* Absolute Helix name */
596 const char *ref_type, /* Reference type */
597 char *types[], /* Address type of data to operate on */
598 const char *new_str /* String to bind to name */
601 NS_Reference_t *ref = NULL;
602 const NS_ReferenceAddress_t *addr = NULL;
603 NS_ReferenceAddress_t *new_addr = NULL;
604 NS_CompositeName_t *comp_name;
605 NS_ContextStatus_t *status = NULL;
606 NS_Context_t *ctx = NULL;
608 void *iter_pos = NULL;
612 if (libfns_handle == NULL) {
616 /* Get the reference from the name */
617 if ((ref = dtfns_lookup_ref(name)) != NULL) {
619 * A value is already bound to this name.
620 * Get the address that matches at least one of
621 * the specified types
623 addr = dtfns_addr_from_ref(ref, types, &iter_pos);
625 /* Get string bound to that address */
627 dtfns_str_from_addr(addr, buf, sizeof(buf), NULL, 0);
629 /* Are we changing the string? */
630 if (strcmp(buf, new_str) == 0) {
631 /* Bound value is the same as new value */
635 /* Delete old address string */
636 (*NS_Reference_delete_addr_p)(ref, &iter_pos);
640 /* Nothing bound to name. Create an empty reference */
641 nstr = (*NS_String_from_cstring_p)(ref_type);
642 ref = (*NS_Reference_new_p)(nstr);
646 /* Create new address */
647 if ((new_addr = dtfns_create_str_addr(new_str, types[0])) == NULL) {
651 /* Insert new address into reference */
652 if (dtfns_insert_addr(ref, &iter_pos, new_addr) < 1) {
656 /* Bind reference into name space */
657 if ((ctx = dtfns_get_initial_ctx()) == NULL) {
661 status = (*NS_ContextStatus_new_p)();
662 comp_name = (*NS_CompositeName_from_cstring_p)(name);
664 if ((*NS_Context_bind_p)(ctx, comp_name, ref, 0, status) < 1) {
671 /* Clean up and return */
672 if (new_addr != NULL) (*NS_ReferenceAddress_delete_p)(new_addr);
673 if (ref != NULL) (*NS_Reference_delete_p)(ref);
674 if (status != NULL) (*NS_ContextStatus_delete_p)(status);
680 * Return the reference bound to an absolute Helix name
684 * NS_Reference_t * for reference
688 const char *name)/* Absolute Helix name to lookup */
691 NS_Reference_t * ref = NULL;
692 NS_ContextStatus_t * status = NULL;
693 NS_CompositeName_t * comp_name = NULL;
696 if (libfns_handle == NULL) {
700 status = (*NS_ContextStatus_new_p)();
701 if ((ctx = dtfns_get_initial_ctx()) != NULL) {
702 /* Lookup the Helix name specified by "name" */
703 comp_name = (*NS_CompositeName_from_cstring_p)(name);
704 ref = (*NS_Context_lookup_p)(ctx, comp_name, status);
707 (*NS_ContextStatus_delete_p)(status);
712 * Takes a Helix name and converts it to a full name for a service.
713 * I.e. if service is "calendar":
716 * org:ss-eng:user:dipol --> org:ss-eng:user:dipol:service:calendar
717 * org:ss-eng --> org:ss-eng:service:calendar
718 * org:ss-eng:service: --> org:ss-eng:service:calendar
721 * -1 Error. buf not set
722 * 0 name already points to the service
723 * buf is a duplicate of name.
724 * 1 name resolved. buf is set. Caller
725 * is responsible for freeing memory.
728 get_helix_service_name(
731 const char *service_type,
743 tmp_name = strdup(name);
745 /* Remove trailing : if there is one */
746 if (tmp_name[n - 1] == ':') {
747 tmp_name[n - 1] = '\0';
751 /* Get reference and extract reference type */
752 if ((ref = dtfns_lookup_ref(tmp_name)) == NULL) {
756 nstr = (*NS_Reference_type_p)(ref);
757 type = (*NS_String_cstring_p)(nstr);
759 (*NS_Reference_delete_p)(ref);
761 /* If name is already bound to a calendar service then we are done */
762 if (strcmp(type, service_type) == 0) {
767 if ((p = strrchr(tmp_name, ':')) != NULL) {
772 * If name is a service context or the "service" null context
773 * then we want to append ":calendar"
775 if (strcmp(type, DTFNS_SERVICE_CONTEXT_TYPE) == 0 ||
776 (strcmp(type, DTFNS_NULL_CONTEXT_TYPE) == 0 && p != NULL &&
777 strcmp(p, DTFNS_SERVICE_NAME) == 0)) {
779 *buf = (char *)malloc(n + strlen(service) + 2);
783 strcpy(*buf, tmp_name);
785 strcat(*buf, service);
788 /* Append ":service:calendar" */
789 *buf = (char *)malloc(n +
790 strlen(DTFNS_SERVICE_NAME) +
791 strlen(service) + 3);
792 sprintf(*buf, "%s:%s:%s", tmp_name,
793 DTFNS_SERVICE_NAME, service);
799 * Get an FNS Address from a Reference.
801 * ref The Reference to get the address from
803 * types NULL terminated array of one or more type strings.
804 * This routine returns the first address that matches
805 * a type specified in this array. NULL to just
806 * get the first address.
808 * iter_pos Updated to point after retrieved address.
811 * Pointer to the found address
812 * NULL if no address is found
815 const NS_ReferenceAddress_t *
817 const NS_Reference_t *ref, /* Reference to get addr from */
818 char *types[], /* Types of addrs to get */
819 void **iter_pos /* Returned pos where addr was found */
823 const NS_ReferenceAddress_t *addr;
827 if (libfns_handle == NULL) {
831 addr = (*NS_Reference_first_p)(ref, iter_pos);
836 while (addr != NULL) {
837 /* Get the type, and see if it is one we want */
838 dtfns_str_from_addr(addr, NULL, 0, type, sizeof(type));
839 for (p = types; *p != NULL && strcmp(*p, type) != 0; *p++)
846 /* Get next address */
847 addr = (*NS_Reference_next_p)(ref, iter_pos);
855 * Get the string and type out of an Address
859 * 0 FNS not available
864 const NS_ReferenceAddress_t *addr, /* Addr to get string from */
865 char *dbuf, /* Buf to hold string data */
866 int dbuf_size, /* Size of dbuf */
867 char *tbuf, /* Buf to hold string type */
868 int tbuf_size /* size of tbuf */
877 if (libfns_handle == NULL) {
882 /* Convert data from XDR to a string */
884 (caddr_t)(*NS_ReferenceAddress_data_p)(addr),
885 (*NS_ReferenceAddress_length_p)(addr), XDR_DECODE);
887 if (xdr_string(&xdr, &s, ~0) == FALSE) {
891 dbuf[dbuf_size - 1] = '\0';
892 strncpy(dbuf, s, dbuf_size - 1);
897 tbuf[tbuf_size - 1] = '\0';
898 nstr = (*NS_ReferenceAddress_type_p)(addr);
899 cs = (*NS_String_cstring_p)(nstr);
900 strncpy(tbuf, cs, tbuf_size - 1);
907 * Create an Address of type "type" for the string specified by "data"
910 * A new address contianing the specified data
913 NS_ReferenceAddress_t *
914 dtfns_create_str_addr(
922 NS_String_t *nstring;
924 if (libfns_handle == NULL) {
928 xdrmem_create(&xdr, (caddr_t)buf, sizeof(buf), XDR_ENCODE);
929 if (xdr_string(&xdr, (char**)&data, ~0) == FALSE) {
933 nstring = (*NS_String_from_cstring_p)(type);
934 return (*NS_ReferenceAddress_new_p)(nstring, xdr_getpos(&xdr), buf);
938 * Add an address to a reference at the location specified by iter_pos.
939 * The address is inserted before iter_pos.
940 * If *iter_pos is NULL then put the address in the first slot.
944 * 0 FNS not available
951 const NS_ReferenceAddress_t *addr
955 if (libfns_handle == NULL) {
959 if (*iter_pos == NULL) {
960 if ((*NS_Reference_prepend_addr_p)(ref, addr) < 1)
963 if ((*NS_Reference_insert_addr_p)(ref, iter_pos, addr) < 1)
971 * Delete the Address at position "iter_pos" from a Reference
975 * 0 FNS not available
985 if (libfns_handle == NULL) {
989 (*NS_Reference_delete_addr_p)(ref, iter_pos);