xref: /illumos-gate/usr/src/cmd/sendmail/libsm/niprop.c (revision 7c478bd9)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 2001 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate  *	All rights reserved.
4*7c478bd9Sstevel@tonic-gate  *
5*7c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
6*7c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
7*7c478bd9Sstevel@tonic-gate  * the sendmail distribution.
8*7c478bd9Sstevel@tonic-gate  */
9*7c478bd9Sstevel@tonic-gate 
10*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
11*7c478bd9Sstevel@tonic-gate 
12*7c478bd9Sstevel@tonic-gate #include <sm/gen.h>
13*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: niprop.c,v 1.6 2001/09/04 22:41:27 ca Exp $")
14*7c478bd9Sstevel@tonic-gate 
15*7c478bd9Sstevel@tonic-gate #if NETINFO
16*7c478bd9Sstevel@tonic-gate #include <ctype.h>
17*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
18*7c478bd9Sstevel@tonic-gate #include <sm/io.h>
19*7c478bd9Sstevel@tonic-gate #include <sm/assert.h>
20*7c478bd9Sstevel@tonic-gate #include <sm/debug.h>
21*7c478bd9Sstevel@tonic-gate #include <sm/string.h>
22*7c478bd9Sstevel@tonic-gate #include <sm/varargs.h>
23*7c478bd9Sstevel@tonic-gate #include <sm/heap.h>
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate /*
26*7c478bd9Sstevel@tonic-gate **  NI_PROPVAL -- NetInfo property value lookup routine
27*7c478bd9Sstevel@tonic-gate **
28*7c478bd9Sstevel@tonic-gate **	Parameters:
29*7c478bd9Sstevel@tonic-gate **		keydir -- the NetInfo directory name in which to search
30*7c478bd9Sstevel@tonic-gate **			for the key.
31*7c478bd9Sstevel@tonic-gate **		keyprop -- the name of the property in which to find the
32*7c478bd9Sstevel@tonic-gate **			property we are interested.  Defaults to "name".
33*7c478bd9Sstevel@tonic-gate **		keyval -- the value for which we are really searching.
34*7c478bd9Sstevel@tonic-gate **		valprop -- the property name for the value in which we
35*7c478bd9Sstevel@tonic-gate **			are interested.
36*7c478bd9Sstevel@tonic-gate **		sepchar -- if non-nil, this can be multiple-valued, and
37*7c478bd9Sstevel@tonic-gate **			we should return a string separated by this
38*7c478bd9Sstevel@tonic-gate **			character.
39*7c478bd9Sstevel@tonic-gate **
40*7c478bd9Sstevel@tonic-gate **	Returns:
41*7c478bd9Sstevel@tonic-gate **		NULL -- if:
42*7c478bd9Sstevel@tonic-gate **			1. the directory is not found
43*7c478bd9Sstevel@tonic-gate **			2. the property name is not found
44*7c478bd9Sstevel@tonic-gate **			3. the property contains multiple values
45*7c478bd9Sstevel@tonic-gate **			4. some error occurred
46*7c478bd9Sstevel@tonic-gate **		else -- the value of the lookup.
47*7c478bd9Sstevel@tonic-gate **
48*7c478bd9Sstevel@tonic-gate **	Example:
49*7c478bd9Sstevel@tonic-gate **		To search for an alias value, use:
50*7c478bd9Sstevel@tonic-gate **		  ni_propval("/aliases", "name", aliasname, "members", ',')
51*7c478bd9Sstevel@tonic-gate **
52*7c478bd9Sstevel@tonic-gate **	Notes:
53*7c478bd9Sstevel@tonic-gate **		Caller should free the return value of ni_proval
54*7c478bd9Sstevel@tonic-gate */
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate # include <netinfo/ni.h>
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate # define LOCAL_NETINFO_DOMAIN	"."
59*7c478bd9Sstevel@tonic-gate # define PARENT_NETINFO_DOMAIN	".."
60*7c478bd9Sstevel@tonic-gate # define MAX_NI_LEVELS		256
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate char *
63*7c478bd9Sstevel@tonic-gate ni_propval(keydir, keyprop, keyval, valprop, sepchar)
64*7c478bd9Sstevel@tonic-gate 	char *keydir;
65*7c478bd9Sstevel@tonic-gate 	char *keyprop;
66*7c478bd9Sstevel@tonic-gate 	char *keyval;
67*7c478bd9Sstevel@tonic-gate 	char *valprop;
68*7c478bd9Sstevel@tonic-gate 	int sepchar;
69*7c478bd9Sstevel@tonic-gate {
70*7c478bd9Sstevel@tonic-gate 	char *propval = NULL;
71*7c478bd9Sstevel@tonic-gate 	int i;
72*7c478bd9Sstevel@tonic-gate 	int j, alen, l;
73*7c478bd9Sstevel@tonic-gate 	void *ni = NULL;
74*7c478bd9Sstevel@tonic-gate 	void *lastni = NULL;
75*7c478bd9Sstevel@tonic-gate 	ni_status nis;
76*7c478bd9Sstevel@tonic-gate 	ni_id nid;
77*7c478bd9Sstevel@tonic-gate 	ni_namelist ninl;
78*7c478bd9Sstevel@tonic-gate 	register char *p;
79*7c478bd9Sstevel@tonic-gate 	char keybuf[1024];
80*7c478bd9Sstevel@tonic-gate 
81*7c478bd9Sstevel@tonic-gate 	/*
82*7c478bd9Sstevel@tonic-gate 	**  Create the full key from the two parts.
83*7c478bd9Sstevel@tonic-gate 	**
84*7c478bd9Sstevel@tonic-gate 	**	Note that directory can end with, e.g., "name=" to specify
85*7c478bd9Sstevel@tonic-gate 	**	an alternate search property.
86*7c478bd9Sstevel@tonic-gate 	*/
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate 	i = strlen(keydir) + strlen(keyval) + 2;
89*7c478bd9Sstevel@tonic-gate 	if (keyprop != NULL)
90*7c478bd9Sstevel@tonic-gate 		i += strlen(keyprop) + 1;
91*7c478bd9Sstevel@tonic-gate 	if (i >= sizeof keybuf)
92*7c478bd9Sstevel@tonic-gate 		return NULL;
93*7c478bd9Sstevel@tonic-gate 	(void) sm_strlcpyn(keybuf, sizeof keybuf, 2, keydir, "/");
94*7c478bd9Sstevel@tonic-gate 	if (keyprop != NULL)
95*7c478bd9Sstevel@tonic-gate 	{
96*7c478bd9Sstevel@tonic-gate 		(void) sm_strlcat2(keybuf, keyprop, "=", sizeof keybuf);
97*7c478bd9Sstevel@tonic-gate 	}
98*7c478bd9Sstevel@tonic-gate 	(void) sm_strlcat(keybuf, keyval, sizeof keybuf);
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate #if 0
101*7c478bd9Sstevel@tonic-gate 	if (tTd(38, 21))
102*7c478bd9Sstevel@tonic-gate 		sm_dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n",
103*7c478bd9Sstevel@tonic-gate 			keydir, keyprop, keyval, valprop, sepchar, keybuf);
104*7c478bd9Sstevel@tonic-gate #endif /* 0 */
105*7c478bd9Sstevel@tonic-gate 
106*7c478bd9Sstevel@tonic-gate 	/*
107*7c478bd9Sstevel@tonic-gate 	**  If the passed directory and property name are found
108*7c478bd9Sstevel@tonic-gate 	**  in one of netinfo domains we need to search (starting
109*7c478bd9Sstevel@tonic-gate 	**  from the local domain moving all the way back to the
110*7c478bd9Sstevel@tonic-gate 	**  root domain) set propval to the property's value
111*7c478bd9Sstevel@tonic-gate 	**  and return it.
112*7c478bd9Sstevel@tonic-gate 	*/
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++)
115*7c478bd9Sstevel@tonic-gate 	{
116*7c478bd9Sstevel@tonic-gate 		if (i == 0)
117*7c478bd9Sstevel@tonic-gate 		{
118*7c478bd9Sstevel@tonic-gate 			nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni);
119*7c478bd9Sstevel@tonic-gate #if 0
120*7c478bd9Sstevel@tonic-gate 			if (tTd(38, 20))
121*7c478bd9Sstevel@tonic-gate 				sm_dprintf("ni_open(LOCAL) = %d\n", nis);
122*7c478bd9Sstevel@tonic-gate #endif /* 0 */
123*7c478bd9Sstevel@tonic-gate 		}
124*7c478bd9Sstevel@tonic-gate 		else
125*7c478bd9Sstevel@tonic-gate 		{
126*7c478bd9Sstevel@tonic-gate 			if (lastni != NULL)
127*7c478bd9Sstevel@tonic-gate 				ni_free(lastni);
128*7c478bd9Sstevel@tonic-gate 			lastni = ni;
129*7c478bd9Sstevel@tonic-gate 			nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni);
130*7c478bd9Sstevel@tonic-gate #if 0
131*7c478bd9Sstevel@tonic-gate 			if (tTd(38, 20))
132*7c478bd9Sstevel@tonic-gate 				sm_dprintf("ni_open(PARENT) = %d\n", nis);
133*7c478bd9Sstevel@tonic-gate #endif /* 0 */
134*7c478bd9Sstevel@tonic-gate 		}
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 		/*
137*7c478bd9Sstevel@tonic-gate 		**  Don't bother if we didn't get a handle on a
138*7c478bd9Sstevel@tonic-gate 		**  proper domain.  This is not necessarily an error.
139*7c478bd9Sstevel@tonic-gate 		**  We would get a positive ni_status if, for instance
140*7c478bd9Sstevel@tonic-gate 		**  we never found the directory or property and tried
141*7c478bd9Sstevel@tonic-gate 		**  to open the parent of the root domain!
142*7c478bd9Sstevel@tonic-gate 		*/
143*7c478bd9Sstevel@tonic-gate 
144*7c478bd9Sstevel@tonic-gate 		if (nis != 0)
145*7c478bd9Sstevel@tonic-gate 			break;
146*7c478bd9Sstevel@tonic-gate 
147*7c478bd9Sstevel@tonic-gate 		/*
148*7c478bd9Sstevel@tonic-gate 		**  Find the path to the server information.
149*7c478bd9Sstevel@tonic-gate 		*/
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 		if (ni_pathsearch(ni, &nid, keybuf) != 0)
152*7c478bd9Sstevel@tonic-gate 			continue;
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 		/*
155*7c478bd9Sstevel@tonic-gate 		**  Find associated value information.
156*7c478bd9Sstevel@tonic-gate 		*/
157*7c478bd9Sstevel@tonic-gate 
158*7c478bd9Sstevel@tonic-gate 		if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0)
159*7c478bd9Sstevel@tonic-gate 			continue;
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate #if 0
162*7c478bd9Sstevel@tonic-gate 		if (tTd(38, 20))
163*7c478bd9Sstevel@tonic-gate 			sm_dprintf("ni_lookupprop: len=%d\n",
164*7c478bd9Sstevel@tonic-gate 				ninl.ni_namelist_len);
165*7c478bd9Sstevel@tonic-gate #endif /* 0 */
166*7c478bd9Sstevel@tonic-gate 
167*7c478bd9Sstevel@tonic-gate 		/*
168*7c478bd9Sstevel@tonic-gate 		**  See if we have an acceptable number of values.
169*7c478bd9Sstevel@tonic-gate 		*/
170*7c478bd9Sstevel@tonic-gate 
171*7c478bd9Sstevel@tonic-gate 		if (ninl.ni_namelist_len <= 0)
172*7c478bd9Sstevel@tonic-gate 			continue;
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 		if (sepchar == '\0' && ninl.ni_namelist_len > 1)
175*7c478bd9Sstevel@tonic-gate 		{
176*7c478bd9Sstevel@tonic-gate 			ni_namelist_free(&ninl);
177*7c478bd9Sstevel@tonic-gate 			continue;
178*7c478bd9Sstevel@tonic-gate 		}
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate 		/*
181*7c478bd9Sstevel@tonic-gate 		**  Calculate number of bytes needed and build result
182*7c478bd9Sstevel@tonic-gate 		*/
183*7c478bd9Sstevel@tonic-gate 
184*7c478bd9Sstevel@tonic-gate 		alen = 1;
185*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < ninl.ni_namelist_len; j++)
186*7c478bd9Sstevel@tonic-gate 			alen += strlen(ninl.ni_namelist_val[j]) + 1;
187*7c478bd9Sstevel@tonic-gate 		propval = p = sm_malloc(alen);
188*7c478bd9Sstevel@tonic-gate 		if (propval == NULL)
189*7c478bd9Sstevel@tonic-gate 			goto cleanup;
190*7c478bd9Sstevel@tonic-gate 		for (j = 0; j < ninl.ni_namelist_len; j++)
191*7c478bd9Sstevel@tonic-gate 		{
192*7c478bd9Sstevel@tonic-gate 			(void) sm_strlcpy(p, ninl.ni_namelist_val[j], alen);
193*7c478bd9Sstevel@tonic-gate 			l = strlen(p);
194*7c478bd9Sstevel@tonic-gate 			p += l;
195*7c478bd9Sstevel@tonic-gate 			*p++ = sepchar;
196*7c478bd9Sstevel@tonic-gate 			alen -= l + 1;
197*7c478bd9Sstevel@tonic-gate 		}
198*7c478bd9Sstevel@tonic-gate 		*--p = '\0';
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate 		ni_namelist_free(&ninl);
201*7c478bd9Sstevel@tonic-gate 	}
202*7c478bd9Sstevel@tonic-gate 
203*7c478bd9Sstevel@tonic-gate   cleanup:
204*7c478bd9Sstevel@tonic-gate 	if (ni != NULL)
205*7c478bd9Sstevel@tonic-gate 		ni_free(ni);
206*7c478bd9Sstevel@tonic-gate 	if (lastni != NULL && ni != lastni)
207*7c478bd9Sstevel@tonic-gate 		ni_free(lastni);
208*7c478bd9Sstevel@tonic-gate #if 0
209*7c478bd9Sstevel@tonic-gate 	if (tTd(38, 20))
210*7c478bd9Sstevel@tonic-gate 		sm_dprintf("ni_propval returns: '%s'\n", propval);
211*7c478bd9Sstevel@tonic-gate #endif /* 0 */
212*7c478bd9Sstevel@tonic-gate 
213*7c478bd9Sstevel@tonic-gate 	return propval;
214*7c478bd9Sstevel@tonic-gate }
215*7c478bd9Sstevel@tonic-gate #endif /* NETINFO */
216