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