Import sendmail 8.13.7
[dragonfly.git] / contrib / sendmail-8.13.7 / libsm / niprop.c
blobad58867cf013adb90d1d652494f5726f042bb8d1
1 /*
2 * Copyright (c) 2001 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
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 */
10 #include <sm/gen.h>
11 SM_RCSID("@(#)$Id: niprop.c,v 1.8 2001/09/11 04:04:48 gshapiro Exp $")
13 #if NETINFO
14 #include <ctype.h>
15 #include <stdlib.h>
16 #include <sm/io.h>
17 #include <sm/assert.h>
18 #include <sm/debug.h>
19 #include <sm/string.h>
20 #include <sm/varargs.h>
21 #include <sm/heap.h>
24 ** NI_PROPVAL -- NetInfo property value lookup routine
26 ** Parameters:
27 ** keydir -- the NetInfo directory name in which to search
28 ** for the key.
29 ** keyprop -- the name of the property in which to find the
30 ** property we are interested. Defaults to "name".
31 ** keyval -- the value for which we are really searching.
32 ** valprop -- the property name for the value in which we
33 ** are interested.
34 ** sepchar -- if non-nil, this can be multiple-valued, and
35 ** we should return a string separated by this
36 ** character.
38 ** Returns:
39 ** NULL -- if:
40 ** 1. the directory is not found
41 ** 2. the property name is not found
42 ** 3. the property contains multiple values
43 ** 4. some error occurred
44 ** else -- the value of the lookup.
46 ** Example:
47 ** To search for an alias value, use:
48 ** ni_propval("/aliases", "name", aliasname, "members", ',')
50 ** Notes:
51 ** Caller should free the return value of ni_proval
54 # include <netinfo/ni.h>
56 # define LOCAL_NETINFO_DOMAIN "."
57 # define PARENT_NETINFO_DOMAIN ".."
58 # define MAX_NI_LEVELS 256
60 char *
61 ni_propval(keydir, keyprop, keyval, valprop, sepchar)
62 char *keydir;
63 char *keyprop;
64 char *keyval;
65 char *valprop;
66 int sepchar;
68 char *propval = NULL;
69 int i;
70 int j, alen, l;
71 void *ni = NULL;
72 void *lastni = NULL;
73 ni_status nis;
74 ni_id nid;
75 ni_namelist ninl;
76 register char *p;
77 char keybuf[1024];
80 ** Create the full key from the two parts.
82 ** Note that directory can end with, e.g., "name=" to specify
83 ** an alternate search property.
86 i = strlen(keydir) + strlen(keyval) + 2;
87 if (keyprop != NULL)
88 i += strlen(keyprop) + 1;
89 if (i >= sizeof keybuf)
90 return NULL;
91 (void) sm_strlcpyn(keybuf, sizeof keybuf, 2, keydir, "/");
92 if (keyprop != NULL)
94 (void) sm_strlcat2(keybuf, keyprop, "=", sizeof keybuf);
96 (void) sm_strlcat(keybuf, keyval, sizeof keybuf);
98 #if 0
99 if (tTd(38, 21))
100 sm_dprintf("ni_propval(%s, %s, %s, %s, %d) keybuf='%s'\n",
101 keydir, keyprop, keyval, valprop, sepchar, keybuf);
102 #endif /* 0 */
105 ** If the passed directory and property name are found
106 ** in one of netinfo domains we need to search (starting
107 ** from the local domain moving all the way back to the
108 ** root domain) set propval to the property's value
109 ** and return it.
112 for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++)
114 if (i == 0)
116 nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni);
117 #if 0
118 if (tTd(38, 20))
119 sm_dprintf("ni_open(LOCAL) = %d\n", nis);
120 #endif /* 0 */
122 else
124 if (lastni != NULL)
125 ni_free(lastni);
126 lastni = ni;
127 nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni);
128 #if 0
129 if (tTd(38, 20))
130 sm_dprintf("ni_open(PARENT) = %d\n", nis);
131 #endif /* 0 */
135 ** Don't bother if we didn't get a handle on a
136 ** proper domain. This is not necessarily an error.
137 ** We would get a positive ni_status if, for instance
138 ** we never found the directory or property and tried
139 ** to open the parent of the root domain!
142 if (nis != 0)
143 break;
146 ** Find the path to the server information.
149 if (ni_pathsearch(ni, &nid, keybuf) != 0)
150 continue;
153 ** Find associated value information.
156 if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0)
157 continue;
159 #if 0
160 if (tTd(38, 20))
161 sm_dprintf("ni_lookupprop: len=%d\n",
162 ninl.ni_namelist_len);
163 #endif /* 0 */
166 ** See if we have an acceptable number of values.
169 if (ninl.ni_namelist_len <= 0)
170 continue;
172 if (sepchar == '\0' && ninl.ni_namelist_len > 1)
174 ni_namelist_free(&ninl);
175 continue;
179 ** Calculate number of bytes needed and build result
182 alen = 1;
183 for (j = 0; j < ninl.ni_namelist_len; j++)
184 alen += strlen(ninl.ni_namelist_val[j]) + 1;
185 propval = p = sm_malloc(alen);
186 if (propval == NULL)
187 goto cleanup;
188 for (j = 0; j < ninl.ni_namelist_len; j++)
190 (void) sm_strlcpy(p, ninl.ni_namelist_val[j], alen);
191 l = strlen(p);
192 p += l;
193 *p++ = sepchar;
194 alen -= l + 1;
196 *--p = '\0';
198 ni_namelist_free(&ninl);
201 cleanup:
202 if (ni != NULL)
203 ni_free(ni);
204 if (lastni != NULL && ni != lastni)
205 ni_free(lastni);
206 #if 0
207 if (tTd(38, 20))
208 sm_dprintf("ni_propval returns: '%s'\n", propval);
209 #endif /* 0 */
211 return propval;
213 #endif /* NETINFO */