/* * 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_RCSID("@(#)$Id: niprop.c,v 1.8 2001/09/11 04:04:48 gshapiro Exp $") #if NETINFO #include #include #include #include #include #include #include #include /* ** 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 # 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 */