diff options
Diffstat (limited to 'contrib/sendmail/libsm/niprop.c')
-rw-r--r-- | contrib/sendmail/libsm/niprop.c | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/contrib/sendmail/libsm/niprop.c b/contrib/sendmail/libsm/niprop.c new file mode 100644 index 0000000..ad58867 --- /dev/null +++ b/contrib/sendmail/libsm/niprop.c @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + */ + +#include <sm/gen.h> +SM_RCSID("@(#)$Id: niprop.c,v 1.8 2001/09/11 04:04:48 gshapiro Exp $") + +#if NETINFO +#include <ctype.h> +#include <stdlib.h> +#include <sm/io.h> +#include <sm/assert.h> +#include <sm/debug.h> +#include <sm/string.h> +#include <sm/varargs.h> +#include <sm/heap.h> + +/* +** NI_PROPVAL -- NetInfo property value lookup routine +** +** Parameters: +** keydir -- the NetInfo directory name in which to search +** for the key. +** keyprop -- the name of the property in which to find the +** property we are interested. Defaults to "name". +** keyval -- the value for which we are really searching. +** valprop -- the property name for the value in which we +** are interested. +** sepchar -- if non-nil, this can be multiple-valued, and +** we should return a string separated by this +** character. +** +** Returns: +** NULL -- if: +** 1. the directory is not found +** 2. the property name is not found +** 3. the property contains multiple values +** 4. some error occurred +** else -- the value of the lookup. +** +** Example: +** To search for an alias value, use: +** ni_propval("/aliases", "name", aliasname, "members", ',') +** +** Notes: +** Caller should free the return value of ni_proval +*/ + +# include <netinfo/ni.h> + +# define LOCAL_NETINFO_DOMAIN "." +# define PARENT_NETINFO_DOMAIN ".." +# define MAX_NI_LEVELS 256 + +char * +ni_propval(keydir, keyprop, keyval, valprop, sepchar) + char *keydir; + char *keyprop; + char *keyval; + char *valprop; + int sepchar; +{ + char *propval = NULL; + int i; + int j, alen, l; + void *ni = NULL; + void *lastni = NULL; + ni_status nis; + ni_id nid; + ni_namelist ninl; + register char *p; + char keybuf[1024]; + + /* + ** Create the full key from the two parts. + ** + ** Note that directory can end with, e.g., "name=" to specify + ** an alternate search property. + */ + + i = strlen(keydir) + strlen(keyval) + 2; + if (keyprop != NULL) + i += strlen(keyprop) + 1; + if (i >= sizeof keybuf) + return NULL; + (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, keydir, "/"); + if (keyprop != NULL) + { + (void) sm_strlcat2(keybuf, keyprop, "=", sizeof keybuf); + } + (void) sm_strlcat(keybuf, keyval, sizeof keybuf); + +#if 0 + if (tTd(38, 21)) + sm_dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n", + keydir, keyprop, keyval, valprop, sepchar, keybuf); +#endif /* 0 */ + + /* + ** If the passed directory and property name are found + ** in one of netinfo domains we need to search (starting + ** from the local domain moving all the way back to the + ** root domain) set propval to the property's value + ** and return it. + */ + + for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++) + { + if (i == 0) + { + nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); +#if 0 + if (tTd(38, 20)) + sm_dprintf("ni_open(LOCAL) = %d\n", nis); +#endif /* 0 */ + } + else + { + if (lastni != NULL) + ni_free(lastni); + lastni = ni; + nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); +#if 0 + if (tTd(38, 20)) + sm_dprintf("ni_open(PARENT) = %d\n", nis); +#endif /* 0 */ + } + + /* + ** Don't bother if we didn't get a handle on a + ** proper domain. This is not necessarily an error. + ** We would get a positive ni_status if, for instance + ** we never found the directory or property and tried + ** to open the parent of the root domain! + */ + + if (nis != 0) + break; + + /* + ** Find the path to the server information. + */ + + if (ni_pathsearch(ni, &nid, keybuf) != 0) + continue; + + /* + ** Find associated value information. + */ + + if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) + continue; + +#if 0 + if (tTd(38, 20)) + sm_dprintf("ni_lookupprop: len=%d\n", + ninl.ni_namelist_len); +#endif /* 0 */ + + /* + ** See if we have an acceptable number of values. + */ + + if (ninl.ni_namelist_len <= 0) + continue; + + if (sepchar == '\0' && ninl.ni_namelist_len > 1) + { + ni_namelist_free(&ninl); + continue; + } + + /* + ** Calculate number of bytes needed and build result + */ + + alen = 1; + for (j = 0; j < ninl.ni_namelist_len; j++) + alen += strlen(ninl.ni_namelist_val[j]) + 1; + propval = p = sm_malloc(alen); + if (propval == NULL) + goto cleanup; + for (j = 0; j < ninl.ni_namelist_len; j++) + { + (void) sm_strlcpy(p, ninl.ni_namelist_val[j], alen); + l = strlen(p); + p += l; + *p++ = sepchar; + alen -= l + 1; + } + *--p = '\0'; + + ni_namelist_free(&ninl); + } + + cleanup: + if (ni != NULL) + ni_free(ni); + if (lastni != NULL && ni != lastni) + ni_free(lastni); +#if 0 + if (tTd(38, 20)) + sm_dprintf("ni_propval returns: '%s'\n", propval); +#endif /* 0 */ + + return propval; +} +#endif /* NETINFO */ |