Libinfo-173.tar.gz
[apple/libinfo.git] / lookup.subproj / lu_bootparam.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 * Bootparams lookup - netinfo only
27 * Copyright (C) 1989 by NeXT, Inc.
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 <bootparams.h>
36
37 #include "lookup.h"
38 #include "_lu_types.h"
39 #include "lu_utils.h"
40
41 static void
42 free_bootparams_data(struct bootparamsent *b)
43 {
44 char **param;
45
46 if (b == NULL) return;
47
48 if (b->bp_name != NULL) free(b->bp_name);
49
50 param = b->bp_bootparams;
51 if (param != NULL)
52 {
53 while (*param != NULL) free(*param++);
54 free(b->bp_bootparams);
55 }
56 }
57
58 static void
59 free_bootparams(struct bootparamsent *b)
60 {
61 if (b == NULL) return;
62 free_bootparams_data(b);
63 free(b);
64 }
65
66 static void
67 free_lu_thread_info_bootparams(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_bootparams((struct bootparamsent *)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 bootparamsent *
87 extract_bootparams(XDR *xdr)
88 {
89 int i, j, nkeys, nvals, status;
90 char *key, **vals;
91 struct bootparamsent *b;
92
93 if (xdr == NULL) return NULL;
94
95 if (!xdr_int(xdr, &nkeys)) return NULL;
96
97 b = (struct bootparamsent *)calloc(1, sizeof(struct bootparamsent));
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_bootparams(b);
109 return NULL;
110 }
111
112 if (nvals == 0)
113 {
114 free(key);
115 continue;
116 }
117
118 j = 0;
119
120 if ((b->bp_name == NULL) && (!strcmp("name", key)))
121 {
122 b->bp_name = vals[0];
123 j = 1;
124 }
125 else if ((b->bp_bootparams == NULL) && (!strcmp("bootparams", key)))
126 {
127 b->bp_bootparams = vals;
128 j = nvals;
129 vals = NULL;
130 }
131
132 free(key);
133 if (vals != NULL)
134 {
135 for (; j < nvals; j++) free(vals[j]);
136 free(vals);
137 }
138 }
139
140 if (b->bp_name == NULL) b->bp_name = strdup("");
141 if (b->bp_bootparams == NULL) b->bp_bootparams = (char **)calloc(1, sizeof(char *));
142
143 return b;
144 }
145
146 static void
147 recycle_bootparams(struct lu_thread_info *tdata, struct bootparamsent *in)
148 {
149 struct bootparamsent *b;
150
151 if (tdata == NULL) return;
152 b = (struct bootparamsent *)tdata->lu_entry;
153
154 if (in == NULL)
155 {
156 free_bootparams(b);
157 tdata->lu_entry = NULL;
158 }
159
160 if (tdata->lu_entry == NULL)
161 {
162 tdata->lu_entry = in;
163 return;
164 }
165
166 free_bootparams_data(b);
167
168 b->bp_name = in->bp_name;
169 b->bp_bootparams = in->bp_bootparams;
170
171 free(in);
172 }
173
174 static struct bootparamsent *
175 lu_bootparams_getbyname(const char *name)
176 {
177 struct bootparamsent *b;
178 unsigned datalen;
179 char namebuf[_LU_MAXLUSTRLEN + BYTES_PER_XDR_UNIT];
180 char *lookup_buf;
181 XDR outxdr;
182 XDR inxdr;
183 int size;
184 static int proc = -1;
185 int count;
186
187 if (proc < 0)
188 {
189 if (_lookup_link(_lu_port, "bootparams_getbyname", &proc)
190 != KERN_SUCCESS)
191 {
192 return (NULL);
193 }
194 }
195
196 xdrmem_create(&outxdr, namebuf, sizeof(namebuf), XDR_ENCODE);
197 if (!xdr__lu_string(&outxdr, (_lu_string *)&name))
198 {
199 xdr_destroy(&outxdr);
200 return (NULL);
201 }
202
203 size = xdr_getpos(&outxdr);
204 xdr_destroy(&outxdr);
205
206 datalen = 0;
207 lookup_buf = NULL;
208
209 if (_lookup_all(_lu_port, proc, (unit *)namebuf, size, &lookup_buf,
210 &datalen) != KERN_SUCCESS)
211 {
212 return (NULL);
213 }
214
215 datalen *= BYTES_PER_XDR_UNIT;
216 if ((lookup_buf == NULL) || (datalen == 0)) return NULL;
217
218 xdrmem_create(&inxdr, lookup_buf, datalen, XDR_DECODE);
219
220 count = 0;
221 if (!xdr_int(&inxdr, &count))
222 {
223 xdr_destroy(&inxdr);
224 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
225 return NULL;
226 }
227
228 if (count == 0)
229 {
230 xdr_destroy(&inxdr);
231 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
232 return NULL;
233 }
234
235 b = extract_bootparams(&inxdr);
236 xdr_destroy(&inxdr);
237 vm_deallocate(mach_task_self(), (vm_address_t)lookup_buf, datalen);
238
239 return b;
240 }
241
242 static void
243 lu_bootparams_endent(void)
244 {
245 struct lu_thread_info *tdata;
246
247 tdata = _lu_data_create_key(_lu_data_key_bootparams, free_lu_thread_info_bootparams);
248 _lu_data_free_vm_xdr(tdata);
249 }
250
251 static void
252 lu_bootparams_setent(void)
253 {
254 lu_bootparams_endent();
255 }
256
257 static struct bootparamsent *
258 lu_bootparams_getent(void)
259 {
260 struct bootparamsent *b;
261 static int proc = -1;
262 struct lu_thread_info *tdata;
263
264 tdata = _lu_data_create_key(_lu_data_key_bootparams, free_lu_thread_info_bootparams);
265 if (tdata == NULL)
266 {
267 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
268 _lu_data_set_key(_lu_data_key_bootparams, tdata);
269 }
270
271 if (tdata->lu_vm == NULL)
272 {
273 if (proc < 0)
274 {
275 if (_lookup_link(_lu_port, "bootparams_getent", &proc) != KERN_SUCCESS)
276 {
277 lu_bootparams_endent();
278 return NULL;
279 }
280 }
281
282 if (_lookup_all(_lu_port, proc, NULL, 0, &(tdata->lu_vm), &(tdata->lu_vm_length)) != KERN_SUCCESS)
283 {
284 lu_bootparams_endent();
285 return NULL;
286 }
287
288 /* mig stubs measure size in words (4 bytes) */
289 tdata->lu_vm_length *= 4;
290
291 if (tdata->lu_xdr != NULL)
292 {
293 xdr_destroy(tdata->lu_xdr);
294 free(tdata->lu_xdr);
295 }
296 tdata->lu_xdr = (XDR *)calloc(1, sizeof(XDR));
297
298 xdrmem_create(tdata->lu_xdr, tdata->lu_vm, tdata->lu_vm_length, XDR_DECODE);
299 if (!xdr_int(tdata->lu_xdr, &tdata->lu_vm_cursor))
300 {
301 lu_bootparams_endent();
302 return NULL;
303 }
304 }
305
306 if (tdata->lu_vm_cursor == 0)
307 {
308 lu_bootparams_endent();
309 return NULL;
310 }
311
312 b = extract_bootparams(tdata->lu_xdr);
313 if (b == NULL)
314 {
315 lu_bootparams_endent();
316 return NULL;
317 }
318
319 tdata->lu_vm_cursor--;
320
321 return b;
322 }
323
324 struct bootparamsent *
325 bootparams_getbyname(const char *name)
326 {
327 struct bootparamsent *res;
328 struct lu_thread_info *tdata;
329
330 tdata = _lu_data_create_key(_lu_data_key_bootparams, free_lu_thread_info_bootparams);
331 if (tdata == NULL)
332 {
333 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
334 _lu_data_set_key(_lu_data_key_bootparams, tdata);
335 }
336
337 if (_lu_running())
338 {
339 res = lu_bootparams_getbyname(name);
340 recycle_bootparams(tdata, res);
341 return (struct bootparamsent *)tdata->lu_entry;
342 }
343
344 return NULL;
345 }
346
347 struct bootparamsent *
348 bootparams_getent(void)
349 {
350 struct bootparamsent *res;
351 struct lu_thread_info *tdata;
352
353 tdata = _lu_data_create_key(_lu_data_key_bootparams, free_lu_thread_info_bootparams);
354 if (tdata == NULL)
355 {
356 tdata = (struct lu_thread_info *)calloc(1, sizeof(struct lu_thread_info));
357 _lu_data_set_key(_lu_data_key_bootparams, tdata);
358 }
359
360 if (_lu_running())
361 {
362 res = lu_bootparams_getent();
363 recycle_bootparams(tdata, res);
364 return (struct bootparamsent *)tdata->lu_entry;
365 }
366
367 return NULL;
368 }
369
370 void
371 bootparams_setent(void)
372 {
373 if (_lu_running()) lu_bootparams_setent();
374 }
375
376 void
377 bootparams_endent(void)
378 {
379 if (_lu_running()) lu_bootparams_endent();
380 }