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 | #include <sm/gen.h> |
---|
11 | SM_RCSID("@(#)$Id: niprop.c,v 1.1.1.1 2003-04-08 15:06:04 zacheiss Exp $") |
---|
12 | |
---|
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> |
---|
22 | |
---|
23 | /* |
---|
24 | ** NI_PROPVAL -- NetInfo property value lookup routine |
---|
25 | ** |
---|
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. |
---|
37 | ** |
---|
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. |
---|
45 | ** |
---|
46 | ** Example: |
---|
47 | ** To search for an alias value, use: |
---|
48 | ** ni_propval("/aliases", "name", aliasname, "members", ',') |
---|
49 | ** |
---|
50 | ** Notes: |
---|
51 | ** Caller should free the return value of ni_proval |
---|
52 | */ |
---|
53 | |
---|
54 | # include <netinfo/ni.h> |
---|
55 | |
---|
56 | # define LOCAL_NETINFO_DOMAIN "." |
---|
57 | # define PARENT_NETINFO_DOMAIN ".." |
---|
58 | # define MAX_NI_LEVELS 256 |
---|
59 | |
---|
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; |
---|
67 | { |
---|
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]; |
---|
78 | |
---|
79 | /* |
---|
80 | ** Create the full key from the two parts. |
---|
81 | ** |
---|
82 | ** Note that directory can end with, e.g., "name=" to specify |
---|
83 | ** an alternate search property. |
---|
84 | */ |
---|
85 | |
---|
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) |
---|
93 | { |
---|
94 | (void) sm_strlcat2(keybuf, keyprop, "=", sizeof keybuf); |
---|
95 | } |
---|
96 | (void) sm_strlcat(keybuf, keyval, sizeof keybuf); |
---|
97 | |
---|
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 */ |
---|
103 | |
---|
104 | /* |
---|
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. |
---|
110 | */ |
---|
111 | |
---|
112 | for (i = 0; i < MAX_NI_LEVELS && propval == NULL; i++) |
---|
113 | { |
---|
114 | if (i == 0) |
---|
115 | { |
---|
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 */ |
---|
121 | } |
---|
122 | else |
---|
123 | { |
---|
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 */ |
---|
132 | } |
---|
133 | |
---|
134 | /* |
---|
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! |
---|
140 | */ |
---|
141 | |
---|
142 | if (nis != 0) |
---|
143 | break; |
---|
144 | |
---|
145 | /* |
---|
146 | ** Find the path to the server information. |
---|
147 | */ |
---|
148 | |
---|
149 | if (ni_pathsearch(ni, &nid, keybuf) != 0) |
---|
150 | continue; |
---|
151 | |
---|
152 | /* |
---|
153 | ** Find associated value information. |
---|
154 | */ |
---|
155 | |
---|
156 | if (ni_lookupprop(ni, &nid, valprop, &ninl) != 0) |
---|
157 | continue; |
---|
158 | |
---|
159 | #if 0 |
---|
160 | if (tTd(38, 20)) |
---|
161 | sm_dprintf("ni_lookupprop: len=%d\n", |
---|
162 | ninl.ni_namelist_len); |
---|
163 | #endif /* 0 */ |
---|
164 | |
---|
165 | /* |
---|
166 | ** See if we have an acceptable number of values. |
---|
167 | */ |
---|
168 | |
---|
169 | if (ninl.ni_namelist_len <= 0) |
---|
170 | continue; |
---|
171 | |
---|
172 | if (sepchar == '\0' && ninl.ni_namelist_len > 1) |
---|
173 | { |
---|
174 | ni_namelist_free(&ninl); |
---|
175 | continue; |
---|
176 | } |
---|
177 | |
---|
178 | /* |
---|
179 | ** Calculate number of bytes needed and build result |
---|
180 | */ |
---|
181 | |
---|
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++) |
---|
189 | { |
---|
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; |
---|
195 | } |
---|
196 | *--p = '\0'; |
---|
197 | |
---|
198 | ni_namelist_free(&ninl); |
---|
199 | } |
---|
200 | |
---|
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 */ |
---|
210 | |
---|
211 | return propval; |
---|
212 | } |
---|
213 | #endif /* NETINFO */ |
---|