Libinfo-78.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_utils.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.1 (the "License"). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <mach/mach.h>
28
29 #include "_lu_types.h"
30 #include "lookup.h"
31 #include "lu_utils.h"
32
33 #define LONG_STRING_LENGTH 8192
34 #define _LU_MAXLUSTRLEN 256
35
36 static ni_proplist *
37 lookupd_process_dictionary(XDR *inxdr)
38 {
39 int i, nkeys, j, nvals;
40 char *key, *val;
41 ni_proplist *l;
42
43 if (!xdr_int(inxdr, &nkeys)) return NULL;
44
45 l = (ni_proplist *)malloc(sizeof(ni_proplist));
46 NI_INIT(l);
47
48 l->ni_proplist_len = nkeys;
49 l->ni_proplist_val = NULL;
50 if (nkeys > 0)
51 {
52 i = nkeys * sizeof(ni_property);
53 l->ni_proplist_val = (ni_property *)malloc(i);
54 memset(l->ni_proplist_val, 0, i);
55 }
56
57 for (i = 0; i < nkeys; i++)
58 {
59 key = NULL;
60
61 if (!xdr_string(inxdr, &key, LONG_STRING_LENGTH))
62 {
63 ni_proplist_free(l);
64 return NULL;
65 }
66
67 l->ni_proplist_val[i].nip_name = key;
68
69 if (!xdr_int(inxdr, &nvals))
70 {
71 ni_proplist_free(l);
72 return NULL;
73 }
74
75 l->ni_proplist_val[i].nip_val.ni_namelist_len = nvals;
76 if (nvals > 0)
77 {
78 j = nvals * sizeof(ni_name);
79 l->ni_proplist_val[i].nip_val.ni_namelist_val = (ni_name *)malloc(j);
80 memset(l->ni_proplist_val[i].nip_val.ni_namelist_val, 0 , j);
81 }
82
83 for (j = 0; j < nvals; j++)
84 {
85 val = NULL;
86 if (!xdr_string(inxdr, &val, LONG_STRING_LENGTH))
87 {
88 ni_proplist_free(l);
89 return NULL;
90 }
91
92 l->ni_proplist_val[i].nip_val.ni_namelist_val[j] = val;
93 }
94 }
95
96 return l;
97 }
98
99 int
100 lookupd_query(ni_proplist *l, ni_proplist ***out)
101 {
102 unsigned datalen;
103 XDR outxdr;
104 XDR inxdr;
105 int proc;
106 char *listbuf;
107 char databuf[_LU_MAXLUSTRLEN * BYTES_PER_XDR_UNIT];
108 int n, i, j, na;
109 kern_return_t status;
110 ni_property *p;
111
112 if (l == NULL) return 0;
113 if (out == NULL) return 0;
114
115 if (_lu_port == NULL) return 0;
116
117 status = _lookup_link(_lu_port, "query", &proc);
118 if (status != KERN_SUCCESS) return 0;
119
120 xdrmem_create(&outxdr, databuf, sizeof(databuf), XDR_ENCODE);
121
122 na = l->ni_proplist_len;
123
124 /* Encode attribute count */
125 if (!xdr_int(&outxdr, &na))
126 {
127 xdr_destroy(&outxdr);
128 return 0;
129 }
130
131 for (i = 0; i < l->ni_proplist_len; i++)
132 {
133 p = &(l->ni_proplist_val[i]);
134 if (!xdr_string(&outxdr, &(p->nip_name), _LU_MAXLUSTRLEN))
135 {
136 xdr_destroy(&outxdr);
137 return 0;
138 }
139
140 if (!xdr_int(&outxdr, &(p->nip_val.ni_namelist_len)))
141 {
142 xdr_destroy(&outxdr);
143 return 0;
144 }
145
146 for (j = 0; j < p->nip_val.ni_namelist_len; j++)
147 {
148 if (!xdr_string(&outxdr, &(p->nip_val.ni_namelist_val[j]), _LU_MAXLUSTRLEN))
149 {
150 xdr_destroy(&outxdr);
151 return 0;
152 }
153 }
154 }
155
156 listbuf = NULL;
157 datalen = 0;
158
159 n = xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT;
160 status = _lookup_all(_lu_port, proc, (unit *)databuf, n, &listbuf, &datalen);
161 if (status != KERN_SUCCESS)
162 {
163 xdr_destroy(&outxdr);
164 return 0;
165 }
166
167 xdr_destroy(&outxdr);
168
169 #ifdef NOTDEF
170 /* NOTDEF because OOL buffers are counted in bytes with untyped IPC */
171 datalen *= BYTES_PER_XDR_UNIT;
172 #endif
173
174 xdrmem_create(&inxdr, listbuf, datalen, XDR_DECODE);
175
176 if (!xdr_int(&inxdr, &n))
177 {
178 xdr_destroy(&inxdr);
179 return 0;
180 }
181
182 if (n == 0)
183 {
184 xdr_destroy(&inxdr);
185 return 0;
186 }
187
188 *out = (ni_proplist **)malloc(n * sizeof(ni_proplist *));
189
190 for (i = 0; i < n; i++)
191 {
192 (*out)[i] = lookupd_process_dictionary(&inxdr);
193 }
194
195 xdr_destroy(&inxdr);
196
197 vm_deallocate(mach_task_self(), (vm_address_t)listbuf, datalen);
198
199 return n;
200 }
201
202 ni_proplist *
203 lookupd_make_query(char *cat, char *fmt, ...)
204 {
205 va_list ap;
206 char *arg, *f;
207 int na, x;
208 ni_proplist *l;
209 ni_property *p;
210
211 if (fmt == NULL) return NULL;
212 if (fmt[0] != 'k') return NULL;
213
214 l = (ni_proplist *)malloc(sizeof(ni_proplist));
215 NI_INIT(l);
216
217 na = 0;
218 x = -1;
219
220 if (cat != NULL)
221 {
222 l->ni_proplist_val = (ni_property *)malloc(sizeof(ni_property));
223 p = &(l->ni_proplist_val[0]);
224 arg = "_lookup_category";
225 p->nip_name = strdup(arg);
226 p->nip_val.ni_namelist_len = 1;
227 p->nip_val.ni_namelist_val = (ni_name *)malloc(sizeof(ni_name));
228 p->nip_val.ni_namelist_val[0] = strdup(cat);
229
230 l->ni_proplist_len++;
231 x++;
232 }
233
234 va_start(ap, fmt);
235 for (f = fmt; *f != NULL; f++)
236 {
237 arg = va_arg(ap, char *);
238 if (*f == 'k')
239 {
240 l->ni_proplist_val = (ni_property *)realloc(l->ni_proplist_val, (l->ni_proplist_len + 1) * sizeof(ni_property));
241
242 p = &(l->ni_proplist_val[l->ni_proplist_len]);
243 p->nip_name = strdup(arg);
244 p->nip_val.ni_namelist_len = 0;
245 p->nip_val.ni_namelist_val = NULL;
246
247 l->ni_proplist_len++;
248 x++;
249 }
250 else
251 {
252 p = &(l->ni_proplist_val[x]);
253 if (p->nip_val.ni_namelist_len == 0)
254 {
255 p->nip_val.ni_namelist_val = (ni_name *)malloc(sizeof(ni_name));
256 }
257 else
258 {
259 p->nip_val.ni_namelist_val = (ni_name *)realloc(p->nip_val.ni_namelist_val, (p->nip_val.ni_namelist_len + 1) * sizeof(ni_name));
260 }
261 p->nip_val.ni_namelist_val[p->nip_val.ni_namelist_len] = strdup(arg);
262 p->nip_val.ni_namelist_len++;
263 }
264 }
265 va_end(ap);
266
267 return l;
268 }
269
270 void
271 ni_property_merge(ni_property *a, ni_property *b)
272 {
273 int i, j, addme;
274
275 if (a == NULL) return;
276 if (b == NULL) return;
277
278 for (j = 0; j < b->nip_val.ni_namelist_len; j++)
279 {
280 addme = 1;
281 for (i = 0; i < (a->nip_val.ni_namelist_len) && (addme == 1); i++)
282 {
283 if (!strcmp(a->nip_val.ni_namelist_val[i], b->nip_val.ni_namelist_val[j])) addme = 0;
284 }
285
286 if (addme == 1)
287 {
288 a->nip_val.ni_namelist_val = (ni_name *)realloc(a->nip_val.ni_namelist_val, (a->nip_val.ni_namelist_len + 1) * sizeof(ni_name));
289 a->nip_val.ni_namelist_val[a->nip_val.ni_namelist_len] = strdup(b->nip_val.ni_namelist_val[j]);
290 a->nip_val.ni_namelist_len++;
291 }
292 }
293 }
294
295 void
296 ni_proplist_merge(ni_proplist *a, ni_proplist *b)
297 {
298 ni_index wa, wb;
299 int addme;
300
301 if (a == NULL) return;
302 if (b == NULL) return;
303
304 for (wb = 0; wb < b->ni_proplist_len; wb++)
305 {
306 addme = 1;
307 for (wa = 0; (wa < a->ni_proplist_len) && (addme == 1) ; wa++)
308 {
309 if (!strcmp(a->ni_proplist_val[wa].nip_name, b->ni_proplist_val[wb].nip_name)) addme = 0;
310 }
311 if (addme == 1)
312 {
313 a->ni_proplist_val = (ni_property *)realloc(a->ni_proplist_val, (a->ni_proplist_len + 1) * sizeof(ni_property));
314 a->ni_proplist_val[a->ni_proplist_len].nip_name = strdup(b->ni_proplist_val[wb].nip_name);
315 a->ni_proplist_val[a->ni_proplist_len].nip_val.ni_namelist_len = 0;
316 a->ni_proplist_val[a->ni_proplist_len].nip_val.ni_namelist_val = NULL;
317 a->ni_proplist_len++;
318 }
319 }
320
321 for (wb = 0; wb < b->ni_proplist_len; wb++)
322 {
323 for (wa = 0; wa < a->ni_proplist_len; wa++)
324 {
325 if (!strcmp(a->ni_proplist_val[wa].nip_name, b->ni_proplist_val[wb].nip_name))
326 {
327 ni_property_merge(&(a->ni_proplist_val[wa]), &(b->ni_proplist_val[wb]));
328 }
329 }
330 }
331 }
332