Libinfo-129.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_alias.c
1 /*
2 * Copyright (c) 1999-2002 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 * Alias lookup
26 * Copyright (C) 1989 by NeXT, Inc.
27 */
28
29 #include <stdlib.h>
30 #include <mach/mach.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <rpc/types.h>
34 #include <rpc/xdr.h>
35 #include <aliasdb.h>
36 #include <pthread.h>
37
38 #include "_lu_types.h"
39 #include "lookup.h"
40 #include "lu_utils.h"
41 #include "lu_overrides.h"
42
43 static pthread_mutex_t _alias_lock = PTHREAD_MUTEX_INITIALIZER;
44
45 static void
46 free_alias_data(struct aliasent *a)
47 {
48 int i;
49
50 if (a == NULL) return;
51
52 if (a->alias_name != NULL) free(a->alias_name);
53 for (i = 0; i < a->alias_members_len; i++) free(a->alias_members[i]);
54 if (a->alias_members != NULL) free(a->alias_members);
55 }
56
57 static void
58 free_alias(struct aliasent *a)
59 {
60 if (a == NULL) return;
61 free_alias_data(a);
62 free(a);
63 }
64
65 static void
66 free_lu_thread_info_alias(void *x)
67 {
68 struct lu_thread_info *tdata;
69
70 if (x == NULL) return;
71
72 tdata = (struct lu_thread_info *)x;
73
74 if (tdata->lu_entry != NULL)
75 {
76 free_alias((struct aliasent *)tdata->lu_entry);
77 tdata->lu_entry = NULL;
78 }
79
80 _lu_data_free_vm_xdr(tdata);
81
82 free(tdata);
83 }
84
85 static struct aliasent *
86 extract_alias(XDR *xdr)
87 {
88 int i, j, nkeys, nvals, status;
89 char *key, **vals;
90 struct aliasent *a;
91
92 if (xdr == NULL) return NULL;
93
94 if (!xdr_int(xdr, &nkeys)) return NULL;
95
96 a = (struct aliasent *)calloc(1, sizeof(struct aliasent));
97
98 for (i = 0; i < nkeys; i++)
99 {
100 key = NULL;
101 vals = NULL;
102 nvals = 0;
103
104 status = _lu_xdr_attribute(xdr, &key, &vals, &nvals);
105 if (status < 0)
106 {
107 free_alias(a);
108 return NULL;
109 }
110
111 if (nvals == 0)
112 {
113 free(key);
114 continue;
115 }
116
117 j = 0;
118
119 if ((a->alias_name == NULL) && (!strcmp("name", key)))
120 {
121 a->alias_name = vals[0];
122 j = 1;
123 }
124 else if (!strcmp("alias_local", key))
125 {
126 a->alias_local = atoi(vals[0]);
127 }
128 else if ((a->alias_members == NULL) && (!strcmp("members", key)))
129 {
130 a->alias_members_len = nvals;
131 a->alias_members = vals;
132 j = nvals;
133 vals = NULL;
134 }
135
136 free(key);
137 if (vals != NULL)
138 {
139 for (; j < nvals; j++) free(vals[j]);
140 free(vals);
141 }
142 }
143
144 if (a->alias_name == NULL) a->alias_name = strdup("");
145 if (a->alias_members == NULL) a->alias_members = (char **)calloc(1, sizeof(char *));
146
147 return a;
148 }
149
150 static struct aliasent *
151 copy_alias(struct aliasent *in)
152 {
153 int i;
154 struct aliasent *a;
155
156 if (in == NULL) return NULL;
157
158 a = (struct aliasent *)calloc(1, sizeof(struct aliasent));
159
160 a->alias_name = LU_COPY_STRING(in->alias_name);
161
162 a->alias_members_len = in->alias_members_len;
163
164 if (a->alias_members_len == 0)
165 {
166 a->alias_members = (char **)calloc(1, sizeof(char *));
167 }
168 else
169 {
170 a->alias_members = (char **)calloc(a->alias_members_len, sizeof(char *));
171 }
172
173 for (i = 0; i < a->alias_members_len; i++)
174 {
175 a->alias_members[i] = strdup(in->alias_members[i]);
176 }
177
178 a->alias_local = in->alias_local;
179
180 return a;
181 }
182
183 static void
184 recycle_alias(struct lu_thread_info *tdata, struct aliasent *in)
185 {
186 struct aliasent *a;
187
188 if (tdata == NULL) return;
189 a = (struct aliasent *)tdata->lu_entry;
190
191 if (in == NULL)
192 {
193 free_alias(a);
194 tdata->lu_entry = NULL;
195 }
196
197 if (tdata->lu_entry == NULL)
198 {
199 tdata->lu_entry = in;
200 return;
201 }
202
203 free_alias_data(a);
204
205 a->alias_name = in->alias_name;
206 a->alias_members_len = in->alias_members_len;
207 a->alias_members = in->alias_members;
208 a->alias_local = in->alias_local;
209
210 free(in);
211 }
212
213 static struct aliasent *
214 lu_alias_getbyname(const char *name)
215 {
216 struct aliasent *a;
217 unsigned int datalen;
218 char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
219 char *lookup_buf;
220 XDR outxdr;
221 XDR inxdr;
222 static int proc = -1;
223 int count;
224
225 if (proc < 0)
226 {
227 if (_lookup_link(_lu_port, "alias_getbyname", &proc) != KERN_SUCCESS)
228 {
229 return NULL;
230 }
231 }
232
233 xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
234 if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
235 {
236 xdr_destroy(&outxdr);
237 return NULL;
238 }
239
240 datalen = 0;
241 lookup_buf = NULL;
242
243 if (_lookup_all(_lu_port, proc, (unit *)namebuf,
244 xdr_getpos(&outxdr) / BYTES_PER_XDR_UNIT, &lookup_buf, &datalen)
245 != KERN_SUCCESS)
246 {
247 xdr_destroy(&outxdr);
248 return NULL;
249 }
250
251 xdr_destroy(&outxdr);
252
253 datalen *= BYTES_PER_XDR_UNIT;
254 if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
255
256 xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
257
258 count = 0;
259 if (!xdr_int(&inxdr, &count))
260 {
261 xdr_destroy(&inxdr);
262 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
263 return NULL;
264 }
265
266 if (count == 0)
267 {
268 xdr_destroy(&inxdr);
269 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
270 return NULL;
271 }
272
273 a = extract_alias(&inxdr);
274 xdr_destroy(&inxdr);
275 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
276
277 return a;
278 }
279
280 static void
281 lu_alias_endent(void)
282 {
283 struct lu_thread_info *tdata;
284
285 tdata = _lu_data_create_key(_lu_data_key_alias, free_lu_thread_info_alias);
286 _lu_data_free_vm_xdr(tdata);
287 }
288
289 static void
290 lu_alias_setent(void)
291 {
292 lu_alias_endent();
293 }
294
295 static struct aliasent *
296 lu_alias_getent(void)
297 {
298 static int proc = -1;
299 struct lu_thread_info *tdata;
300 struct aliasent *a;
301
302 tdata = _lu_data_create_key(_lu_data_key_alias, free_lu_thread_info_alias);
303 if (tdata == NULL)
304 {
305 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
306 _lu_data_set_key(_lu_data_key_alias, tdata);
307 }
308
309 if (tdata->lu_vm == NULL)
310 {
311 if (proc < 0)
312 {
313 if (_lookup_link(_lu_port, "alias_getent", &proc) != KERN_SUCCESS)
314 {
315 lu_alias_endent();
316 return NULL;
317 }
318 }
319
320 if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
321 {
322 lu_alias_endent();
323 return NULL;
324 }
325
326 /* mig stubs measure size in words (4 bytes) */
327 tdata->lu_vm_length *= 4;
328
329 if (tdata->lu_xdr != NULL)
330 {
331 xdr_destroy(tdata->lu_xdr);
332 free(tdata->lu_xdr);
333 }
334 tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
335
336 xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
337 if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
338 {
339 lu_alias_endent();
340 return NULL;
341 }
342 }
343
344 if (tdata->lu_vm_cursor == 0)
345 {
346 lu_alias_endent();
347 return NULL;
348 }
349
350
351 a = extract_alias(tdata->lu_xdr);
352 if (a == NULL)
353 {
354 lu_alias_endent();
355 return NULL;
356 }
357
358 tdata->lu_vm_cursor--;
359
360 return a;
361 }
362
363 struct aliasent *
364 alias_getbyname(const char *name)
365 {
366 struct aliasent *res = NULL;
367 struct lu_thread_info *tdata;
368
369 tdata = _lu_data_create_key(_lu_data_key_alias, free_lu_thread_info_alias);
370 if (tdata == NULL)
371 {
372 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
373 _lu_data_set_key(_lu_data_key_alias, tdata);
374 }
375
376 if (_lu_running())
377 {
378 res = lu_alias_getbyname(name);
379 }
380 else
381 {
382 pthread_mutex_lock(&_alias_lock);
383 res = copy_alias(_old_alias_getbyname(name));
384 pthread_mutex_unlock(&_alias_lock);
385 }
386
387 recycle_alias(tdata, res);
388 return (struct aliasent *)tdata->lu_entry;
389
390 }
391
392 struct aliasent *
393 alias_getent(void)
394 {
395 struct aliasent *res = NULL;
396 struct lu_thread_info *tdata;
397
398 tdata = _lu_data_create_key(_lu_data_key_alias, free_lu_thread_info_alias);
399 if (tdata == NULL)
400 {
401 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
402 _lu_data_set_key(_lu_data_key_alias, tdata);
403 }
404
405 if (_lu_running())
406 {
407 res = lu_alias_getent();
408 }
409 else
410 {
411 pthread_mutex_lock(&_alias_lock);
412 res = copy_alias(_old_alias_getent());
413 pthread_mutex_unlock(&_alias_lock);
414 }
415
416 recycle_alias(tdata, res);
417 return (struct aliasent *)tdata->lu_entry;
418
419 }
420
421 void
422 alias_setent(void)
423 {
424 if (_lu_running()) lu_alias_setent();
425 else _old_alias_setent();
426 }
427
428 void
429 alias_endent(void)
430 {
431 if (_lu_running()) lu_alias_endent();
432 else _old_alias_endent();
433 }