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