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