Libinfo-173.tar.gz
[apple/libinfo.git] / netinfo.subproj / ni_util.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25 /*
26 * Utility routines for netinfo data structures
27 * Copyright (C) 1989 by NeXT, Inc.
28 */
29 #include <netinfo/ni.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <strings.h>
33 #include <regex.h>
34 #include "mm.h"
35
36 void
37 ni_idlist_insert(
38 ni_idlist *cl,
39 ni_index id,
40 ni_index where
41 )
42 {
43 ni_index i;
44
45 MM_GROW_ARRAY(cl->niil_val, cl->niil_len);
46 for (i = cl->niil_len; i > where; i--) {
47 cl->niil_val[i] = cl->niil_val[i - 1];
48 }
49 cl->niil_val[i] = id;
50 cl->niil_len++;
51 }
52
53 int
54 ni_idlist_delete(
55 ni_idlist *idlist,
56 ni_index id
57 )
58 {
59 ni_index j;
60 ni_index i;
61
62 for (i = 0; i < idlist->niil_len; i++) {
63 if (idlist->niil_val[i] == id) {
64 for (j = i + 1; j < idlist->niil_len; j++) {
65 idlist->niil_val[j - 1] = idlist->niil_val[j];
66 }
67 MM_SHRINK_ARRAY(idlist->niil_val, idlist->niil_len--);
68 return(1);
69 }
70 }
71 return (0);
72 }
73
74
75 void
76 ni_idlist_free(
77 ni_idlist *idlist
78 )
79 {
80 if (idlist->niil_val != NULL) {
81 MM_FREE_ARRAY(idlist->niil_val, idlist->niil_len);
82 }
83 NI_INIT(idlist);
84 }
85
86 ni_idlist
87 ni_idlist_dup(
88 const ni_idlist idlist
89 )
90 {
91 ni_idlist newlist;
92 ni_index i;
93
94 newlist.niil_len = idlist.niil_len;
95 MM_ALLOC_ARRAY(newlist.niil_val, idlist.niil_len);
96 for (i = 0; i < idlist.niil_len; i++) {
97 newlist.niil_val[i] = idlist.niil_val[i];
98 }
99 return (newlist);
100 }
101
102 void
103 ni_proplist_insert(
104 ni_proplist *pl,
105 const ni_property prop,
106 ni_index where
107 )
108 {
109 ni_index i;
110
111 MM_GROW_ARRAY(pl->nipl_val, pl->nipl_len);
112 for (i = pl->nipl_len; i > where; i--) {
113 pl->nipl_val[i] = pl->nipl_val[i - 1];
114 }
115 pl->nipl_val[i] = ni_prop_dup(prop);
116 pl->nipl_len++;
117 }
118
119 void
120 ni_proplist_delete(
121 ni_proplist *pl,
122 ni_index which
123 )
124 {
125 int i;
126
127 ni_prop_free(&pl->nipl_val[which]);
128 for (i = which + 1; i < pl->nipl_len; i++) {
129 pl->nipl_val[i - 1] = pl->nipl_val[i];
130 }
131 MM_SHRINK_ARRAY(pl->nipl_val, pl->nipl_len--);
132 }
133
134 void
135 ni_proplist_free(
136 ni_proplist *pl
137 )
138 {
139 ni_index i;
140
141 if (pl->nipl_val == NULL) {
142 return;
143 }
144 for (i = 0; i < pl->nipl_len; i++) {
145 ni_prop_free(&pl->nipl_val[i]);
146 }
147 MM_FREE_ARRAY(pl->nipl_val, pl->nipl_len);
148 NI_INIT(pl);
149 }
150
151 void
152 ni_proplist_list_free(
153 ni_proplist_list *pll
154 )
155 {
156 ni_index i;
157
158 if (pll->nipll_val == NULL) {
159 return;
160 }
161 for (i = 0; i < pll->nipll_len; i++) {
162 ni_proplist_free(&pll->nipll_val[i]);
163 }
164 MM_FREE_ARRAY(pll->nipll_val, pll->nipll_len);
165 NI_INIT(pll);
166 }
167
168 ni_proplist
169 ni_proplist_dup(
170 const ni_proplist pl
171 )
172 {
173 ni_proplist newlist;
174 ni_index i;
175
176 newlist.nipl_len = pl.nipl_len;
177 MM_ALLOC_ARRAY(newlist.nipl_val, pl.nipl_len);
178 for (i = 0; i < pl.nipl_len; i++) {
179 newlist.nipl_val[i].nip_name = ni_name_dup(pl.nipl_val[i].nip_name);
180 newlist.nipl_val[i].nip_val = ni_namelist_dup(pl.nipl_val[i].nip_val);
181 }
182 return (newlist);
183 }
184
185 ni_index
186 ni_proplist_match(
187 const ni_proplist pl,
188 ni_name_const pname,
189 ni_name_const pval
190 )
191 {
192 ni_index i;
193 ni_index j;
194 ni_namelist nl;
195
196 for (i = 0; i < pl.nipl_len; i++) {
197 if (ni_name_match(pname, pl.nipl_val[i].nip_name)) {
198 if (pval == NULL) {
199 return (i);
200 }
201 nl = pl.nipl_val[i].nip_val;
202 for (j = 0; j < nl.ninl_len; j++) {
203 if (ni_name_match(pval, nl.ninl_val[j])) {
204 return (i);
205 }
206 }
207 break;
208 }
209 }
210 return (NI_INDEX_NULL);
211 }
212
213
214 ni_property
215 ni_prop_dup(
216 const ni_property prop
217 )
218 {
219 ni_property newprop;
220
221 newprop.nip_name = ni_name_dup(prop.nip_name);
222 newprop.nip_val = ni_namelist_dup(prop.nip_val);
223 return (newprop);
224 }
225
226 void
227 ni_prop_free(
228 ni_property *prop
229 )
230 {
231 ni_name_free(&prop->nip_name);
232 ni_namelist_free(&prop->nip_val);
233 }
234
235 int
236 ni_name_match(
237 ni_name_const nm1,
238 ni_name_const nm2
239 )
240 {
241 return (strcmp(nm1, nm2) == 0);
242 }
243
244 ni_name
245 ni_name_dup(
246 ni_name_const nm
247 )
248 {
249 return (strcpy(malloc(strlen(nm) + 1), nm));
250 }
251
252
253 void
254 ni_name_free(
255 ni_name *nm
256 )
257 {
258 if (*nm != NULL) {
259 free(*nm);
260 *nm = NULL;
261 }
262 }
263
264 ni_namelist
265 ni_namelist_dup(
266 const ni_namelist nl
267 )
268 {
269 ni_namelist newlist;
270 ni_index i;
271
272 newlist.ninl_len = nl.ninl_len;
273 MM_ALLOC_ARRAY(newlist.ninl_val, newlist.ninl_len);
274 for (i = 0; i < nl.ninl_len; i++) {
275 newlist.ninl_val[i] = ni_name_dup(nl.ninl_val[i]);
276 }
277 return (newlist);
278 }
279
280 void
281 ni_namelist_free(
282 ni_namelist *nl
283 )
284 {
285 ni_index i;
286
287 if (nl->ninl_val == NULL) {
288 return;
289 }
290 for (i = 0; i < nl->ninl_len; i++) {
291 ni_name_free(&nl->ninl_val[i]);
292 }
293 MM_FREE_ARRAY(nl->ninl_val, nl->ninl_len);
294 NI_INIT(nl);
295 }
296
297 void
298 ni_namelist_insert(
299 ni_namelist *nl,
300 ni_name_const nm,
301 ni_index where
302 )
303 {
304 ni_index i;
305
306 MM_GROW_ARRAY(nl->ninl_val, nl->ninl_len);
307 for (i = nl->ninl_len; i > where; i--) {
308 nl->ninl_val[i] = nl->ninl_val[i - 1];
309 }
310 nl->ninl_val[i] = ni_name_dup(nm);
311 nl->ninl_len++;
312 }
313
314 void
315 ni_namelist_delete(
316 ni_namelist *nl,
317 ni_index which
318 )
319 {
320 int i;
321
322 ni_name_free(&nl->ninl_val[which]);
323 for (i = which + 1; i < nl-> ninl_len; i++) {
324 nl->ninl_val[i - 1] = nl->ninl_val[i];
325 }
326 MM_SHRINK_ARRAY(nl->ninl_val, nl->ninl_len--);
327 }
328
329 ni_index
330 ni_namelist_match(
331 const ni_namelist nl,
332 ni_name_const nm
333 )
334 {
335 ni_index i;
336
337 for (i = 0; i < nl.ninl_len; i++) {
338 if (ni_name_match(nl.ninl_val[i], nm)) {
339 return (i);
340 }
341 }
342 return (NI_INDEX_NULL);
343 }
344
345 void
346 ni_entrylist_insert(
347 ni_entrylist *el,
348 const ni_entry en
349 )
350 {
351 ni_entry entry;
352
353 MM_GROW_ARRAY(el->niel_val, el->niel_len);
354 entry.id = en.id;
355 if (en.names != NULL) {
356 MM_ALLOC(entry.names);
357 *entry.names = ni_namelist_dup(*en.names);
358 } else {
359 entry.names = NULL;
360 }
361 el->niel_val[el->niel_len++] = entry;
362 }
363
364 void
365 ni_entrylist_delete(
366 ni_entrylist *el,
367 ni_index which
368 )
369 {
370 int i;
371
372 if (el->niel_val[which].names != NULL) {
373 ni_namelist_free(el->niel_val[which].names);
374 }
375 for (i = which + 1; i < el-> niel_len; i++) {
376 el->niel_val[i - 1] = el->niel_val[i];
377 }
378 MM_SHRINK_ARRAY(el->niel_val, el->niel_len--);
379 }
380
381 void
382 ni_entrylist_free(
383 ni_entrylist *el
384 )
385 {
386 ni_index i;
387
388 if (el->niel_val == NULL) {
389 return;
390 }
391 for (i = 0; i < el->niel_len; i++) {
392 if (el->niel_val[i].names != NULL) {
393 ni_namelist_free(el->niel_val[i].names);
394 MM_FREE(el->niel_val[i].names);
395 }
396 }
397 MM_FREE_ARRAY(el->niel_val, el->niel_len);
398 NI_INIT(el);
399 }
400
401
402
403 /*
404 * We can do this without an addition to the protocol
405 */
406 ni_status
407 ni_lookupprop(
408 void *ni,
409 ni_id *id,
410 ni_name_const pname,
411 ni_namelist *nl
412 )
413 {
414 ni_status status;
415 ni_namelist list;
416 ni_index which;
417
418 NI_INIT(&list);
419 status = ni_listprops(ni, id, &list);
420 if (status != NI_OK) {
421 return (status);
422 }
423 which = ni_namelist_match(list, pname);
424 ni_namelist_free(&list);
425 if (which == NI_INDEX_NULL) {
426 return (NI_NOPROP);
427 }
428 return (ni_readprop(ni, id, which, nl));
429 }
430
431 /*
432 * Search from local domain to root domain to locate a path.
433 */
434 ni_status
435 ni_find(void **dom, ni_id *nid, ni_name dirname, unsigned int timeout)
436 {
437 void *d, *p;
438 ni_id n;
439 ni_status status;
440 struct sockaddr_in addr;
441
442 *dom = NULL;
443 nid->nii_object = NI_INDEX_NULL;
444 nid->nii_instance = NI_INDEX_NULL;
445
446 memset(&addr, 0, sizeof(struct sockaddr_in));
447 addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
448
449 d = ni_connect(&addr, "local");
450 if (d == NULL) return NI_FAILED;
451
452 while (d != NULL)
453 {
454 if (timeout > 0)
455 {
456 ni_setreadtimeout(d, timeout);
457 ni_setabort(d, 1);
458 }
459
460 status = ni_pathsearch(d, &n, dirname);
461 if (status == NI_OK)
462 {
463 *dom = d;
464 *nid = n;
465 return NI_OK;
466 }
467
468 status = ni_open(d, "..", &p);
469 ni_free(d);
470 d = NULL;
471 if (status == NI_OK) d = p;
472 }
473
474 return NI_NODIR;
475 }
476
477 ni_status
478 ni_search(void *handle, ni_id *dir, ni_name name, ni_name expr, int flags, ni_entrylist *entries)
479 {
480 regex_t *cexp;
481 int i, j, found;
482 ni_entrylist el;
483 ni_namelist *nl;
484 ni_status status;
485
486 /* compile the regular expression */
487 cexp = (regex_t *)malloc(sizeof(regex_t));
488 memset(cexp, 0, sizeof(regex_t));
489 i = regcomp(cexp, expr, flags);
490 if (i != 0)
491 {
492 free(cexp);
493 return NI_FAILED;
494 }
495
496 /* get subdirectory list */
497 NI_INIT(&el);
498 status = ni_list(handle, dir, name, &el);
499 if (status != NI_OK)
500 {
501 regfree(cexp);
502 free(cexp);
503 return status;
504 }
505
506 for (i = 0; i < el.ni_entrylist_len; i++)
507 {
508 if (el.ni_entrylist_val[i].names == NULL) continue;
509
510 nl = el.ni_entrylist_val[i].names;
511
512 found = 0;
513 for (j = 0; j < nl->ni_namelist_len; j++)
514 {
515 if (regexec(cexp, nl->ni_namelist_val[j], 0, NULL, 0) != 0) continue;
516 found = 1;
517 break;
518 }
519
520 if (found == 0) continue;
521
522 if (entries->ni_entrylist_len == 0)
523 {
524 entries->ni_entrylist_val = malloc(sizeof(ni_entry));
525 }
526 else
527 {
528 entries->ni_entrylist_val = (ni_entry *)realloc(entries->ni_entrylist_val, (entries->ni_entrylist_len + 1) * sizeof(ni_entry));
529 }
530
531 entries->ni_entrylist_val[entries->ni_entrylist_len].id = el.ni_entrylist_val[i].id;
532 entries->ni_entrylist_val[entries->ni_entrylist_len].names = el.ni_entrylist_val[i].names;
533 el.ni_entrylist_val[i].names = NULL;
534 entries->ni_entrylist_len++;
535 }
536
537 ni_entrylist_free(&el);
538 regfree(cexp);
539 free(cexp);
540
541 return NI_OK;
542 }