190792Sgshapiro/* 2261194Sgshapiro * Copyright (c) 2001 Proofpoint, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * 590792Sgshapiro * By using this file, you agree to the terms and conditions set 690792Sgshapiro * forth in the LICENSE file which can be found at the top level of 790792Sgshapiro * the sendmail distribution. 890792Sgshapiro */ 990792Sgshapiro 1090792Sgshapiro#include <sm/gen.h> 11266527SgshapiroSM_RCSID("@(#)$Id: niprop.c,v 1.9 2013-11-22 20:51:43 ca Exp $") 1290792Sgshapiro 1390792Sgshapiro#if NETINFO 1490792Sgshapiro#include <ctype.h> 1590792Sgshapiro#include <stdlib.h> 1690792Sgshapiro#include <sm/io.h> 1790792Sgshapiro#include <sm/assert.h> 1890792Sgshapiro#include <sm/debug.h> 1990792Sgshapiro#include <sm/string.h> 2090792Sgshapiro#include <sm/varargs.h> 2190792Sgshapiro#include <sm/heap.h> 2290792Sgshapiro 2390792Sgshapiro/* 2490792Sgshapiro** NI_PROPVAL -- NetInfo property value lookup routine 2590792Sgshapiro** 2690792Sgshapiro** Parameters: 2790792Sgshapiro** keydir -- the NetInfo directory name in which to search 2890792Sgshapiro** for the key. 2990792Sgshapiro** keyprop -- the name of the property in which to find the 3090792Sgshapiro** property we are interested. Defaults to "name". 3190792Sgshapiro** keyval -- the value for which we are really searching. 3290792Sgshapiro** valprop -- the property name for the value in which we 3390792Sgshapiro** are interested. 3490792Sgshapiro** sepchar -- if non-nil, this can be multiple-valued, and 3590792Sgshapiro** we should return a string separated by this 3690792Sgshapiro** character. 3790792Sgshapiro** 3890792Sgshapiro** Returns: 3990792Sgshapiro** NULL -- if: 4090792Sgshapiro** 1. the directory is not found 4190792Sgshapiro** 2. the property name is not found 4290792Sgshapiro** 3. the property contains multiple values 4390792Sgshapiro** 4. some error occurred 4490792Sgshapiro** else -- the value of the lookup. 4590792Sgshapiro** 4690792Sgshapiro** Example: 4790792Sgshapiro** To search for an alias value, use: 4890792Sgshapiro** ni_propval("/aliases", "name", aliasname, "members", ',') 4990792Sgshapiro** 5090792Sgshapiro** Notes: 5190792Sgshapiro** Caller should free the return value of ni_proval 5290792Sgshapiro*/ 5390792Sgshapiro 5490792Sgshapiro# include <netinfo/ni.h> 5590792Sgshapiro 5690792Sgshapiro# define LOCAL_NETINFO_DOMAIN "." 5790792Sgshapiro# define PARENT_NETINFO_DOMAIN ".." 5890792Sgshapiro# define MAX_NI_LEVELS 256 5990792Sgshapiro 6090792Sgshapirochar * 6190792Sgshapironi_propval(keydir, keyprop, keyval, valprop, sepchar) 6290792Sgshapiro char *keydir; 6390792Sgshapiro char *keyprop; 6490792Sgshapiro char *keyval; 6590792Sgshapiro char *valprop; 6690792Sgshapiro int sepchar; 6790792Sgshapiro{ 6890792Sgshapiro char *propval = NULL; 6990792Sgshapiro int i; 7090792Sgshapiro int j, alen, l; 7190792Sgshapiro void *ni = NULL; 7290792Sgshapiro void *lastni = NULL; 7390792Sgshapiro ni_status nis; 7490792Sgshapiro ni_id nid; 7590792Sgshapiro ni_namelist ninl; 7690792Sgshapiro register char *p; 7790792Sgshapiro char keybuf[1024]; 7890792Sgshapiro 7990792Sgshapiro /* 8090792Sgshapiro ** Create the full key from the two parts. 8190792Sgshapiro ** 8290792Sgshapiro ** Note that directory can end with, e.g., "name=" to specify 8390792Sgshapiro ** an alternate search property. 8490792Sgshapiro */ 8590792Sgshapiro 8690792Sgshapiro i = strlen(keydir) + strlen(keyval) + 2; 8790792Sgshapiro if (keyprop != NULL) 8890792Sgshapiro i += strlen(keyprop) + 1; 8990792Sgshapiro if (i >= sizeof keybuf) 9090792Sgshapiro return NULL; 9190792Sgshapiro (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, keydir, "/"); 9290792Sgshapiro if (keyprop != NULL) 9390792Sgshapiro { 9490792Sgshapiro (void) sm_strlcat2(keybuf, keyprop, "=", sizeof keybuf); 9590792Sgshapiro } 9690792Sgshapiro (void) sm_strlcat(keybuf, keyval, sizeof keybuf); 9790792Sgshapiro 9890792Sgshapiro#if 0 9990792Sgshapiro if (tTd(38, 21)) 10090792Sgshapiro sm_dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n", 10190792Sgshapiro keydir, keyprop, keyval, valprop, sepchar, keybuf); 102363466Sgshapiro#endif 10390792Sgshapiro 10490792Sgshapiro /* 10590792Sgshapiro ** If the passed directory and property name are found 10690792Sgshapiro ** in one of netinfo domains we need to search (starting 10790792Sgshapiro ** from the local domain moving all the way back to the 10890792Sgshapiro ** root domain) set propval to the property's value 10990792Sgshapiro ** and return it. 11090792Sgshapiro */ 11190792Sgshapiro 11290792Sgshapiro for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++) 11390792Sgshapiro { 11490792Sgshapiro if (i == 0) 11590792Sgshapiro { 11690792Sgshapiro nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni); 11790792Sgshapiro#if 0 11890792Sgshapiro if (tTd(38, 20)) 11990792Sgshapiro sm_dprintf("ni_open(LOCAL) = %d\n", nis); 120363466Sgshapiro#endif 12190792Sgshapiro } 12290792Sgshapiro else 12390792Sgshapiro { 12490792Sgshapiro if (lastni != NULL) 12590792Sgshapiro ni_free(lastni); 12690792Sgshapiro lastni = ni; 12790792Sgshapiro nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni); 12890792Sgshapiro#if 0 12990792Sgshapiro if (tTd(38, 20)) 13090792Sgshapiro sm_dprintf("ni_open(PARENT) = %d\n", nis); 131363466Sgshapiro#endif 13290792Sgshapiro } 13390792Sgshapiro 13490792Sgshapiro /* 13590792Sgshapiro ** Don't bother if we didn't get a handle on a 13690792Sgshapiro ** proper domain. This is not necessarily an error. 13790792Sgshapiro ** We would get a positive ni_status if, for instance 13890792Sgshapiro ** we never found the directory or property and tried 13990792Sgshapiro ** to open the parent of the root domain! 14090792Sgshapiro */ 14190792Sgshapiro 14290792Sgshapiro if (nis != 0) 14390792Sgshapiro break; 14490792Sgshapiro 14590792Sgshapiro /* 14690792Sgshapiro ** Find the path to the server information. 14790792Sgshapiro */ 14890792Sgshapiro 14990792Sgshapiro if (ni_pathsearch(ni, &nid, keybuf) != 0) 15090792Sgshapiro continue; 15190792Sgshapiro 15290792Sgshapiro /* 15390792Sgshapiro ** Find associated value information. 15490792Sgshapiro */ 15590792Sgshapiro 15690792Sgshapiro if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) 15790792Sgshapiro continue; 15890792Sgshapiro 15990792Sgshapiro#if 0 16090792Sgshapiro if (tTd(38, 20)) 16190792Sgshapiro sm_dprintf("ni_lookupprop: len=%d\n", 16290792Sgshapiro ninl.ni_namelist_len); 163363466Sgshapiro#endif 16490792Sgshapiro 16590792Sgshapiro /* 16690792Sgshapiro ** See if we have an acceptable number of values. 16790792Sgshapiro */ 16890792Sgshapiro 16990792Sgshapiro if (ninl.ni_namelist_len <= 0) 17090792Sgshapiro continue; 17190792Sgshapiro 17290792Sgshapiro if (sepchar == '\0' && ninl.ni_namelist_len > 1) 17390792Sgshapiro { 17490792Sgshapiro ni_namelist_free(&ninl); 17590792Sgshapiro continue; 17690792Sgshapiro } 17790792Sgshapiro 17890792Sgshapiro /* 17990792Sgshapiro ** Calculate number of bytes needed and build result 18090792Sgshapiro */ 18190792Sgshapiro 18290792Sgshapiro alen = 1; 18390792Sgshapiro for (j = 0; j < ninl.ni_namelist_len; j++) 18490792Sgshapiro alen += strlen(ninl.ni_namelist_val[j]) + 1; 18590792Sgshapiro propval = p = sm_malloc(alen); 18690792Sgshapiro if (propval == NULL) 18790792Sgshapiro goto cleanup; 18890792Sgshapiro for (j = 0; j < ninl.ni_namelist_len; j++) 18990792Sgshapiro { 19090792Sgshapiro (void) sm_strlcpy(p, ninl.ni_namelist_val[j], alen); 19190792Sgshapiro l = strlen(p); 19290792Sgshapiro p += l; 19390792Sgshapiro *p++ = sepchar; 19490792Sgshapiro alen -= l + 1; 19590792Sgshapiro } 19690792Sgshapiro *--p = '\0'; 19790792Sgshapiro 19890792Sgshapiro ni_namelist_free(&ninl); 19990792Sgshapiro } 20090792Sgshapiro 20190792Sgshapiro cleanup: 20290792Sgshapiro if (ni != NULL) 20390792Sgshapiro ni_free(ni); 20490792Sgshapiro if (lastni != NULL && ni != lastni) 20590792Sgshapiro ni_free(lastni); 20690792Sgshapiro#if 0 20790792Sgshapiro if (tTd(38, 20)) 20890792Sgshapiro sm_dprintf("ni_propval returns: '%s'\n", propval); 209363466Sgshapiro#endif 21090792Sgshapiro 21190792Sgshapiro return propval; 21290792Sgshapiro} 21390792Sgshapiro#endif /* NETINFO */ 214