214 lines
4.7 KiB
C
214 lines
4.7 KiB
C
|
/*
|
||
|
* 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 */
|