1 | /*␊ |
2 | * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.␊ |
3 | *␊ |
4 | * @APPLE_LICENSE_HEADER_START@␊ |
5 | * ␊ |
6 | * Portions Copyright (c) 1999-2003 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 2.0 (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 | * Copyright 1993 NeXT, Inc.␊ |
26 | * All rights reserved.␊ |
27 | */␊ |
28 | ␊ |
29 | #include "bootstruct.h"␊ |
30 | #include "libsaio.h"␊ |
31 | #include "xml.h"␊ |
32 | ␊ |
33 | extern char *Language;␊ |
34 | extern char *LoadableFamilies;␊ |
35 | ␊ |
36 | bool sysConfigValid;␊ |
37 | ␊ |
38 | /*␊ |
39 | * Compare a string to a key with quoted characters␊ |
40 | */␊ |
41 | static inline int␊ |
42 | keyncmp(const char *str, const char *key, int n)␊ |
43 | {␊ |
44 | int c;␊ |
45 | while (n--) {␊ |
46 | ␉c = *key++;␊ |
47 | ␉if (c == '\\') {␊ |
48 | ␉ switch(c = *key++) {␊ |
49 | ␉ case 'n':␊ |
50 | ␉␉c = '\n';␊ |
51 | ␉␉break;␊ |
52 | ␉ case 'r':␊ |
53 | ␉␉c = '\r';␊ |
54 | ␉␉break;␊ |
55 | ␉ case 't':␊ |
56 | ␉␉c = '\t';␊ |
57 | ␉␉break;␊ |
58 | ␉ default:␊ |
59 | ␉␉break;␊ |
60 | ␉ }␊ |
61 | ␉} else if (c == '\"') {␊ |
62 | ␉ /* Premature end of key */␊ |
63 | ␉ return 1;␊ |
64 | ␉}␊ |
65 | ␉if (c != *str++) {␊ |
66 | ␉ return 1;␊ |
67 | ␉}␊ |
68 | }␊ |
69 | return 0;␊ |
70 | }␊ |
71 | ␊ |
72 | #if UNUSED␊ |
73 | ␊ |
74 | static void eatThru(char val, const char **table_p)␊ |
75 | {␊ |
76 | ␉register const char *table = *table_p;␊ |
77 | ␉register bool found = false;␊ |
78 | ␊ |
79 | ␉while (*table && !found)␊ |
80 | ␉{␊ |
81 | ␉␉if (*table == '\\') table += 2;␊ |
82 | ␉␉else␊ |
83 | ␉␉{␊ |
84 | ␉␉␉if (*table == val) found = true;␊ |
85 | ␉␉␉table++;␊ |
86 | ␉␉}␊ |
87 | ␉}␊ |
88 | ␉*table_p = table;␊ |
89 | }␊ |
90 | ␊ |
91 | /* Remove key and its associated value from the table. */␊ |
92 | ␊ |
93 | bool␊ |
94 | removeKeyFromTable(const char *key, char *table)␊ |
95 | {␊ |
96 | register int len;␊ |
97 | register char *tab;␊ |
98 | char *buf;␊ |
99 | ␊ |
100 | len = strlen(key);␊ |
101 | tab = (char *)table;␊ |
102 | buf = (char *)malloc(len + 3);␊ |
103 | ␊ |
104 | sprintf(buf, "\"%s\"", key);␊ |
105 | len = strlen(buf);␊ |
106 | ␊ |
107 | while(*tab) {␊ |
108 | if(strncmp(buf, tab, len) == 0) {␊ |
109 | char c;␊ |
110 | ␊ |
111 | while((c = *(tab + len)) != ';') {␊ |
112 | if(c == 0) {␊ |
113 | len = -1;␊ |
114 | goto out;␊ |
115 | }␊ |
116 | len++;␊ |
117 | }␊ |
118 | len++;␊ |
119 | if(*(tab + len) == '\n') len++;␊ |
120 | goto out;␊ |
121 | }␊ |
122 | tab++;␊ |
123 | }␊ |
124 | len = -1;␊ |
125 | out:␊ |
126 | free(buf);␊ |
127 | ␊ |
128 | if(len == -1) return false;␊ |
129 | ␊ |
130 | while((*tab = *(tab + len))) {␊ |
131 | tab++;␊ |
132 | }␊ |
133 | ␊ |
134 | return true;␊ |
135 | }␊ |
136 | ␊ |
137 | char *␊ |
138 | newStringFromList(␊ |
139 | char **list,␊ |
140 | int *size␊ |
141 | )␊ |
142 | {␊ |
143 | char *begin = *list, *end;␊ |
144 | char *newstr;␊ |
145 | int newsize = *size;␊ |
146 | int bufsize;␊ |
147 | ␊ |
148 | while (*begin && newsize && isspace(*begin)) {␊ |
149 | ␉begin++;␊ |
150 | ␉newsize--;␊ |
151 | }␊ |
152 | end = begin;␊ |
153 | while (*end && newsize && !isspace(*end)) {␊ |
154 | ␉end++;␊ |
155 | ␉newsize--;␊ |
156 | }␊ |
157 | if (begin == end)␊ |
158 | ␉return 0;␊ |
159 | bufsize = end - begin + 1;␊ |
160 | newstr = malloc(bufsize);␊ |
161 | strlcpy(newstr, begin, bufsize);␊ |
162 | *list = end;␊ |
163 | *size = newsize;␊ |
164 | return newstr;␊ |
165 | }␊ |
166 | ␊ |
167 | #endif␊ |
168 | ␊ |
169 | /* ␊ |
170 | * compress == compress escaped characters to one character␊ |
171 | */␊ |
172 | int stringLength(const char *table, int compress)␊ |
173 | {␊ |
174 | ␉int ret = 0;␊ |
175 | ␊ |
176 | ␉while (*table)␊ |
177 | ␉{␊ |
178 | ␉␉if (*table == '\\')␊ |
179 | ␉␉{␊ |
180 | ␉␉␉table += 2;␊ |
181 | ␉␉␉ret += 1 + (compress ? 0 : 1);␊ |
182 | ␉␉}␊ |
183 | ␉␉else␊ |
184 | ␉␉{␊ |
185 | ␉␉␉if (*table == '\"') return ret;␊ |
186 | ␉␉␉ret++;␊ |
187 | ␉␉␉table++;␊ |
188 | ␉␉}␊ |
189 | ␉}␊ |
190 | ␉return ret;␊ |
191 | }␊ |
192 | ␊ |
193 | ␊ |
194 | bool getValueForConfigTableKey(config_file_t *config, const char *key, const char **val, int *size)␊ |
195 | {␊ |
196 | ␉if (config->dictionary != 0 ) {␊ |
197 | ␉␉// Look up key in XML dictionary␊ |
198 | ␉␉TagPtr value;␊ |
199 | ␉␉value = XMLGetProperty(config->dictionary, key);␊ |
200 | ␉␉if (value != 0) {␊ |
201 | ␉␉␉if (value->type != kTagTypeString) {␊ |
202 | ␉␉␉␉error("Non-string tag '%s' found in config file\n",␊ |
203 | ␉␉␉␉␉ key);␊ |
204 | ␉␉␉␉return false;␊ |
205 | ␉␉␉}␊ |
206 | ␉␉␉*val = value->string;␊ |
207 | ␉␉␉*size = strlen(value->string);␊ |
208 | ␉␉␉return true;␊ |
209 | ␉␉}␊ |
210 | ␉} else {␊ |
211 | ␉␊ |
212 | ␉␉// Legacy plist-style table␊ |
213 | ␊ |
214 | ␉}␊ |
215 | ␊ |
216 | ␉return false;␊ |
217 | }␊ |
218 | ␊ |
219 | #if UNUSED␊ |
220 | ␊ |
221 | /*␊ |
222 | * Returns a new malloc'ed string if one is found␊ |
223 | * in the string table matching 'key'. Also translates␊ |
224 | * \n escapes in the string.␊ |
225 | */␊ |
226 | char *newStringForStringTableKey(␊ |
227 | ␉char *table,␊ |
228 | ␉char *key,␊ |
229 | ␉config_file_t *config␊ |
230 | )␊ |
231 | {␊ |
232 | const char *val;␊ |
233 | char *newstr, *p;␊ |
234 | int size;␊ |
235 | ␊ |
236 | if (getValueForConfigTableKey(config, key, &val, &size)) {␊ |
237 | ␉newstr = (char *)malloc(size+1);␊ |
238 | ␉for (p = newstr; size; size--, p++, val++) {␊ |
239 | ␉ if ((*p = *val) == '\\') {␊ |
240 | ␉␉switch (*++val) {␊ |
241 | ␉␉case 'r':␊ |
242 | ␉␉ *p = '\r';␊ |
243 | ␉␉ break;␊ |
244 | ␉␉case 'n':␊ |
245 | ␉␉ *p = '\n';␊ |
246 | ␉␉ break;␊ |
247 | ␉␉case 't':␊ |
248 | ␉␉ *p = '\t';␊ |
249 | ␉␉ break;␊ |
250 | ␉␉default:␊ |
251 | ␉␉ *p = *val;␊ |
252 | ␉␉ break;␊ |
253 | ␉␉}␊ |
254 | ␉␉size--;␊ |
255 | ␉ }␊ |
256 | ␉}␊ |
257 | ␉*p = '\0';␊ |
258 | ␉return newstr;␊ |
259 | } else {␊ |
260 | ␉return 0;␊ |
261 | }␊ |
262 | }␊ |
263 | ␊ |
264 | #endif␊ |
265 | ␊ |
266 | char *␊ |
267 | newStringForKey(char *key, config_file_t *config)␊ |
268 | {␊ |
269 | const char *val;␊ |
270 | char *newstr;␊ |
271 | int size;␊ |
272 | ␊ |
273 | if (getValueForKey(key, &val, &size, config) && size) {␊ |
274 | ␉newstr = (char *)malloc(size + 1);␊ |
275 | ␉strlcpy(newstr, val, size + 1);␊ |
276 | ␉return newstr;␊ |
277 | } else {␊ |
278 | ␉return 0;␊ |
279 | }␊ |
280 | }␊ |
281 | ␊ |
282 | /* parse a command line␊ |
283 | * in the form: [<argument> ...] [<option>=<value> ...]␊ |
284 | * both <option> and <value> must be either composed of␊ |
285 | * non-whitespace characters, or enclosed in quotes.␊ |
286 | */␊ |
287 | ␊ |
288 | static const char *getToken(const char *line, const char **begin, int *len)␊ |
289 | {␊ |
290 | if (*line == '\"') {␊ |
291 | ␉*begin = ++line;␊ |
292 | ␉while (*line && *line != '\"')␊ |
293 | ␉ line++;␊ |
294 | ␉*len = line++ - *begin;␊ |
295 | } else {␊ |
296 | ␉*begin = line;␊ |
297 | ␉while (*line && !isspace(*line) && *line != '=')␊ |
298 | ␉ line++;␊ |
299 | ␉*len = line - *begin;␊ |
300 | }␊ |
301 | return line;␊ |
302 | }␊ |
303 | ␊ |
304 | bool getValueForBootKey(const char *line, const char *match, const char **matchval, int *len)␊ |
305 | {␊ |
306 | const char *key, *value;␊ |
307 | int key_len, value_len;␊ |
308 | bool retval = false;␊ |
309 | ␊ |
310 | while (*line) {␊ |
311 | ␉/* look for keyword or argument */␊ |
312 | ␉while (isspace(*line)) line++;␊ |
313 | ␊ |
314 | ␉/* now look for '=' or whitespace */␊ |
315 | ␉line = getToken(line, &key, &key_len);␊ |
316 | ␉/* line now points to '=' or space */␊ |
317 | ␉if (*line && !isspace(*line)) {␊ |
318 | ␉ line = getToken(++line, &value, &value_len);␊ |
319 | ␉} else {␊ |
320 | ␉ value = line;␊ |
321 | ␉ value_len = 0;␊ |
322 | ␉}␊ |
323 | ␉if ((strlen(match) == key_len)␊ |
324 | ␉ && strncmp(match, key, key_len) == 0) {␊ |
325 | ␉ *matchval = value;␊ |
326 | ␉ *len = value_len;␊ |
327 | ␉ retval = true;␊ |
328 | /* Continue to look for this key; last one wins. */␊ |
329 | ␉}␊ |
330 | }␊ |
331 | return retval;␊ |
332 | }␊ |
333 | ␊ |
334 | /* Return NULL if no option has been successfully retrieved, or the string otherwise */␊ |
335 | const char * getStringForKey(const char * key, config_file_t *config)␊ |
336 | {␊ |
337 | static const char* value =0;␊ |
338 | int len=0;␊ |
339 | if(!getValueForKey(key, &value, &len, config)) value = 0;␊ |
340 | return value;␊ |
341 | }␊ |
342 | ␊ |
343 | ␊ |
344 | /* Returns TRUE if a value was found, FALSE otherwise.␊ |
345 | * The boolean value of the key is stored in 'val'.␊ |
346 | */␊ |
347 | ␊ |
348 | bool getBoolForKey( const char *key, bool *result_val, config_file_t *config )␊ |
349 | {␊ |
350 | const char *key_val;␊ |
351 | int size;␊ |
352 | ␊ |
353 | if (getValueForKey(key, &key_val, &size, config)) {␊ |
354 | if ( (size >= 1) && (key_val[0] == 'Y' || key_val[0] == 'y') ) {␊ |
355 | *result_val = true;␊ |
356 | } else {␊ |
357 | *result_val = false;␊ |
358 | }␊ |
359 | return true;␊ |
360 | }␊ |
361 | return false;␊ |
362 | }␊ |
363 | ␊ |
364 | bool getIntForKey( const char *key, int *value, config_file_t *config )␊ |
365 | {␊ |
366 | const char *val;␊ |
367 | int size, sum;␊ |
368 | bool negative = false;␊ |
369 | ␊ |
370 | if (getValueForKey(key, &val, &size, config))␊ |
371 | ␉{␊ |
372 | ␉␉if ( size )␊ |
373 | ␉␉{␊ |
374 | ␉␉␉if (*val == '-')␊ |
375 | ␉␉␉{␊ |
376 | ␉␉␉␉negative = true;␊ |
377 | ␉␉␉␉val++;␊ |
378 | ␉␉␉␉size--;␊ |
379 | ␉␉␉}␊ |
380 | ␉␉␉␊ |
381 | ␉␉␉for (sum = 0; size > 0; size--)␊ |
382 | ␉␉␉{␊ |
383 | ␉␉␉␉if (*val < '0' || *val > '9')␊ |
384 | ␉␉␉␉␉return false;␊ |
385 | ␉␉␉␉␊ |
386 | ␉␉␉␉sum = (sum * 10) + (*val++ - '0');␊ |
387 | ␉␉␉}␊ |
388 | ␉␉␉␊ |
389 | ␉␉␉if (negative)␊ |
390 | ␉␉␉␉sum = -sum;␊ |
391 | ␉␉␉␊ |
392 | ␉␉␉*value = sum;␊ |
393 | ␉␉␉return true;␊ |
394 | ␉␉}␊ |
395 | ␉}␊ |
396 | return false;␊ |
397 | }␊ |
398 | ␊ |
399 | /*␊ |
400 | // valv: getFloatForKey Begin␊ |
401 | bool getFloatForKey( const char *key, float *value, config_file_t *config )␊ |
402 | {␊ |
403 | const char *val;␊ |
404 | int size;␊ |
405 | float sum;␊ |
406 | ␊ |
407 | if (getValueForKey(key, &val, &size, config))␊ |
408 | ␉{␊ |
409 | ␉␉if ( size )␊ |
410 | ␉␉{␊ |
411 | ␉␉␉if (*val == '-')␊ |
412 | ␉␉␉{␊ |
413 | ␉␉␉␉return false;␊ |
414 | ␉␉␉}␊ |
415 | ␉␉␉␊ |
416 | ␉␉␉for (sum = 0; size > 0; size--)␊ |
417 | ␉␉␉{␊ |
418 | ␉␉␉␉if (*val < '2.5' || *val > '19.5')␊ |
419 | ␉␉␉␉␉return false;␊ |
420 | ␉␉␉␉␊ |
421 | ␉␉␉␉sum = strtof(*val++ - '0');␊ |
422 | ␉␉␉}␊ |
423 | ␉␉␉␊ |
424 | ␉␉␉*value = sum;␊ |
425 | ␉␉␉return true;␊ |
426 | ␉␉}␊ |
427 | ␉}␊ |
428 | return false;␊ |
429 | }␊ |
430 | // valv: getFloatForKey End␊ |
431 | */␊ |
432 | ␊ |
433 | /*␊ |
434 | *␊ |
435 | */␊ |
436 | ␊ |
437 | bool getDimensionForKey( const char *key, unsigned int *value, config_file_t *config, unsigned int dimension_max, unsigned int object_size )␊ |
438 | {␊ |
439 | ␉const char *val;␊ |
440 | ␉␊ |
441 | int size = 0;␊ |
442 | ␉int sum = 0;␊ |
443 | ␊ |
444 | ␉bool negative = false;␊ |
445 | ␉bool percentage = false;␊ |
446 | ␉␊ |
447 | if (getValueForKey(key, &val, &size, config))␊ |
448 | ␉{␊ |
449 | ␉␉if ( size )␊ |
450 | ␉␉{␊ |
451 | ␉␉␉if (*val == '-')␊ |
452 | ␉␉␉{␊ |
453 | ␉␉␉␉negative = true;␊ |
454 | ␉␉␉␉val++;␊ |
455 | ␉␉␉␉size--;␊ |
456 | ␉␉␉}␊ |
457 | ␉␉␉␊ |
458 | ␉␉␉if (val[size-1] == '%')␊ |
459 | ␉␉␉{␊ |
460 | ␉␉␉␉percentage = true;␊ |
461 | ␉␉␉␉size--;␊ |
462 | ␉␉␉}␊ |
463 | ␉␉␉␊ |
464 | ␉␉␉// convert string to integer␊ |
465 | ␉␉␉for (sum = 0; size > 0; size--)␊ |
466 | ␉␉␉{␊ |
467 | ␉␉␉␉if (*val < '0' || *val > '9')␊ |
468 | ␉␉␉␉␉return false;␊ |
469 | ␉␉␉␉␊ |
470 | ␉␉␉␉sum = (sum * 10) + (*val++ - '0');␊ |
471 | ␉␉␉}␊ |
472 | ␉␉␉␊ |
473 | ␉␉␉if (percentage)␊ |
474 | ␉␉␉␉sum = ( dimension_max * sum ) / 100;␊ |
475 | ␉␉␉␊ |
476 | ␉␉␉// calculate offset from opposite origin␊ |
477 | ␉␉␉if (negative)␊ |
478 | ␉␉␉␉sum = ( ( dimension_max - object_size ) - sum );␊ |
479 | ␉␉␉␊ |
480 | ␉␉} else {␊ |
481 | ␉␉␉␊ |
482 | ␉␉␉// null value calculate center␊ |
483 | ␉␉␉sum = ( dimension_max - object_size ) / 2;␊ |
484 | ␉␉␉␊ |
485 | ␉␉}␊ |
486 | ␉␉␊ |
487 | ␉␉*value = (uint16_t) sum;␊ |
488 | ␉␉return true;␊ |
489 | ␉}␊ |
490 | ␉␊ |
491 | ␉// key not found␊ |
492 | return false;␊ |
493 | }␊ |
494 | ␊ |
495 | /*␊ |
496 | *␉get color value from plist format #RRGGBB␊ |
497 | */␊ |
498 | ␊ |
499 | bool getColorForKey( const char *key, unsigned int *value, config_file_t *config )␊ |
500 | {␊ |
501 | const char *val;␊ |
502 | int size;␊ |
503 | ␊ |
504 | if (getValueForKey(key, &val, &size, config))␊ |
505 | ␉{␊ |
506 | ␉␉if (*val == '#')␊ |
507 | ␉␉{␊ |
508 | val++;␊ |
509 | ␉␉␉*value = strtol(val, NULL, 16);␊ |
510 | ␉␉␉return true;␊ |
511 | }␊ |
512 | }␊ |
513 | return false;␊ |
514 | }␊ |
515 | ␊ |
516 | bool getValueForKey( const char *key, const char **val, int *size, config_file_t *config )␊ |
517 | {␊ |
518 | const char *overrideVal;␊ |
519 | int overrideSize;␊ |
520 | bool override, ret;␊ |
521 | ␊ |
522 | if (getValueForBootKey(bootArgs->CommandLine, key, val, size))␊ |
523 | return true;␊ |
524 | ␊ |
525 | ret = getValueForConfigTableKey(config, key, val, size);␊ |
526 | ␊ |
527 | // Try to find alternate keys in bootInfo->overrideConfig␊ |
528 | // and prefer its values with the exceptions for␊ |
529 | // "Kernel"="mach_kernel" and "Kernel Flags"="".␊ |
530 | ␊ |
531 | if (config->canOverride)␊ |
532 | {␊ |
533 | if (getValueForConfigTableKey(&bootInfo->overrideConfig, key, &overrideVal, &overrideSize))␊ |
534 | {␊ |
535 | override = true;␊ |
536 | ␊ |
537 | if (ret && (strcmp(key, "Kernel") == 0) && (strcmp(overrideVal, "mach_kernel") == 0))␊ |
538 | override = false;␊ |
539 | ␊ |
540 | if (ret && (strcmp(key, "Kernel Flags") == 0) && (overrideSize == 0))␊ |
541 | override = false;␊ |
542 | ␊ |
543 | if (override)␊ |
544 | {␊ |
545 | *val = overrideVal;␊ |
546 | *size = overrideSize;␊ |
547 | return true;␊ |
548 | }␊ |
549 | }␊ |
550 | }␊ |
551 | ␊ |
552 | return ret;␊ |
553 | }␊ |
554 | ␊ |
555 | ␊ |
556 | #if UNUSED␊ |
557 | void␊ |
558 | printSystemConfig(char *p1)␊ |
559 | {␊ |
560 | char *p2 = p1, tmp;␊ |
561 | ␊ |
562 | while (*p1 != '\0') {␊ |
563 | ␉while (*p2 != '\0' && *p2 != '\n') p2++;␊ |
564 | ␉tmp = *p2;␊ |
565 | ␉*p2 = '\0';␊ |
566 | ␉printf("%s\n", p1);␊ |
567 | ␉*p2 = tmp;␊ |
568 | ␉if (tmp == '\0') break;␊ |
569 | ␉p1 = ++p2;␊ |
570 | }␊ |
571 | }␊ |
572 | #endif␊ |
573 | ␊ |
574 | //==========================================================================␊ |
575 | // ParseXMLFile␊ |
576 | // Modifies the input buffer.␊ |
577 | // Expects to see one dictionary in the XML file.␊ |
578 | // Puts the first dictionary it finds in the␊ |
579 | // tag pointer and returns 0, or returns -1 if not found␊ |
580 | // (and does not modify dict pointer).␊ |
581 | // Prints an error message if there is a parsing error.␊ |
582 | //␊ |
583 | int ParseXMLFile( char * buffer, TagPtr * dict )␊ |
584 | {␊ |
585 | long length, pos;␊ |
586 | TagPtr tag;␊ |
587 | pos = 0;␊ |
588 | char *configBuffer;␊ |
589 | ␊ |
590 | configBuffer = malloc(strlen(buffer)+1);␊ |
591 | strcpy(configBuffer, buffer);␊ |
592 | ␊ |
593 | while (1)␊ |
594 | {␊ |
595 | length = XMLParseNextTag(configBuffer + pos, &tag);␊ |
596 | if (length == -1) break;␊ |
597 | ␊ |
598 | pos += length;␊ |
599 | ␊ |
600 | if (tag == 0) continue;␊ |
601 | if (tag->type == kTagTypeDict) break;␊ |
602 | ␊ |
603 | XMLFreeTag(tag);␊ |
604 | }␊ |
605 | free(configBuffer);␊ |
606 | if (length < 0) {␊ |
607 | error ("Error parsing plist file\n");␊ |
608 | return -1;␊ |
609 | }␊ |
610 | *dict = tag;␊ |
611 | return 0;␊ |
612 | }␊ |
613 | ␊ |
614 | /* loadConfigFile␊ |
615 | *␊ |
616 | * Returns 0 - successful.␊ |
617 | *␉␉ -1 - unsuccesful.␊ |
618 | */␊ |
619 | int loadConfigFile (const char *configFile, config_file_t *config)␊ |
620 | {␊ |
621 | ␉int fd, count;␊ |
622 | ␊ |
623 | ␉if ((fd = open_bvdev("bt(0,0)", configFile, 0)) < 0) {␊ |
624 | ␉␉return -1;␊ |
625 | ␉}␊ |
626 | ␉// read file␊ |
627 | ␉count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);␊ |
628 | ␉close(fd);␊ |
629 | ␉␊ |
630 | ␉// build xml dictionary␊ |
631 | ␉ParseXMLFile(config->plist, &config->dictionary);␊ |
632 | ␉return 0;␊ |
633 | }␊ |
634 | ␊ |
635 | ␊ |
636 | /* loadSystemConfig␊ |
637 | *␊ |
638 | * Returns 0 - successful.␊ |
639 | *␉␉ -1 - unsuccesful.␊ |
640 | */␊ |
641 | int loadSystemConfig(config_file_t *config)␊ |
642 | {␊ |
643 | ␉char *dirspec[] = {␊ |
644 | ␉␉"bt(0,0)/Extra/com.apple.Boot.plist",␊ |
645 | ␉␉"/Extra/com.apple.Boot.plist",␊ |
646 | ␉␉"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",␊ |
647 | ␉␉"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",␊ |
648 | ␉␉"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",␊ |
649 | ␉␉"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"␊ |
650 | ␉};␊ |
651 | ␊ |
652 | ␉int i, fd, count, ret=-1;␊ |
653 | ␊ |
654 | ␉for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)␊ |
655 | ␉{␊ |
656 | ␉␉if ((fd = open(dirspec[i], 0)) >= 0)␊ |
657 | ␉␉{␊ |
658 | ␉␉␉// read file␊ |
659 | ␉␉␉count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);␊ |
660 | ␉␉␉close(fd);␊ |
661 | ␉␉␉␊ |
662 | ␉␉␉// build xml dictionary␊ |
663 | ␉␉␉ParseXMLFile(config->plist, &config->dictionary);␊ |
664 | ␉␉␉sysConfigValid = true;␉␊ |
665 | ␉␉␉ret=0;␊ |
666 | ␉␉␉␊ |
667 | ␉␉␉// enable canOverride flag␊ |
668 | ␉␉␉config->canOverride = true;␊ |
669 | ␊ |
670 | ␉␉␉break;␊ |
671 | ␉␉}␊ |
672 | ␉}␊ |
673 | ␉return ret;␊ |
674 | }␊ |
675 | ␊ |
676 | /* loadOverrideConfig␊ |
677 | *␊ |
678 | * Returns 0 - successful.␊ |
679 | *␉␉ -1 - unsuccesful.␊ |
680 | */␊ |
681 | int loadOverrideConfig(config_file_t *config)␊ |
682 | {␊ |
683 | ␉char *dirspec[] = {␊ |
684 | ␉␉"rd(0,0)/Extra/com.apple.Boot.plist",␊ |
685 | ␉␉"/Extra/com.apple.Boot.plist",␊ |
686 | ␉␉"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",␊ |
687 | ␉␉"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",␊ |
688 | ␉␉"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",␊ |
689 | ␉␉"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"␊ |
690 | ␉};␊ |
691 | ␊ |
692 | ␉int i, fd, count, ret=-1;␊ |
693 | ␊ |
694 | ␉for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)␊ |
695 | ␉{␊ |
696 | ␉␉if ((fd = open(dirspec[i], 0)) >= 0)␊ |
697 | ␉␉{␊ |
698 | ␉␉␉// read file␊ |
699 | ␉␉␉count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);␊ |
700 | ␉␉␉close(fd);␊ |
701 | ␉␉␉␊ |
702 | ␉␉␉// build xml dictionary␊ |
703 | ␉␉␉ParseXMLFile(config->plist, &config->dictionary);␊ |
704 | ␉␉␉sysConfigValid = true;␉␊ |
705 | ␉␉␉ret=0;␊ |
706 | ␉␉␉break;␊ |
707 | ␉␉}␊ |
708 | ␉}␊ |
709 | ␉return ret;␊ |
710 | }␊ |
711 | ␊ |
712 | /* loadHelperConfig␊ |
713 | *␊ |
714 | * Returns 0 - successful.␊ |
715 | *␉␉ -1 - unsuccesful.␊ |
716 | */␊ |
717 | int loadHelperConfig(config_file_t *config)␊ |
718 | {␊ |
719 | ␉char *dirspec[] = {␊ |
720 | ␉␉"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",␊ |
721 | ␉␉"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",␊ |
722 | ␉␉"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"␊ |
723 | ␉};␊ |
724 | ␊ |
725 | ␉int i, fd, count, ret=-1;␊ |
726 | ␊ |
727 | ␉for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)␊ |
728 | ␉{␊ |
729 | ␉␉if ((fd = open(dirspec[i], 0)) >= 0)␊ |
730 | ␉␉{␊ |
731 | ␉␉␉// read file␊ |
732 | ␉␉␉count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);␊ |
733 | ␉␉␉close(fd);␊ |
734 | ␉␉␉␊ |
735 | ␉␉␉// build xml dictionary␊ |
736 | ␉␉␉ParseXMLFile(config->plist, &config->dictionary);␊ |
737 | ␉␉␉sysConfigValid = true;␉␊ |
738 | ␉␉␉ret=0;␊ |
739 | ␉␉␉break;␊ |
740 | ␉␉}␊ |
741 | ␉}␊ |
742 | ␉return ret;␊ |
743 | }␊ |
744 | ␊ |
745 | char * newString(const char * oldString)␊ |
746 | {␊ |
747 | if ( oldString )␊ |
748 | return strcpy(malloc(strlen(oldString)+1), oldString);␊ |
749 | else␊ |
750 | return NULL;␊ |
751 | }␊ |
752 | ␊ |
753 | /*␊ |
754 | * Extracts the next argument from the command line, double quotes are allowed here.␊ |
755 | */␊ |
756 | char * getNextArg(char ** argPtr, char * val)␊ |
757 | {␊ |
758 | char * ptr = *argPtr;␊ |
759 | const char * strStart;␊ |
760 | int len = 0;␊ |
761 | bool isQuoted = false;␊ |
762 | ␊ |
763 | *val = '\0';␊ |
764 | ␊ |
765 | // Scan for the next non-whitespace character.␊ |
766 | while ( *ptr && (*ptr == ' ' || *ptr == '=') )␊ |
767 | {␊ |
768 | ptr++;␊ |
769 | }␊ |
770 | ␊ |
771 | strStart = ptr;␊ |
772 | ␊ |
773 | // Skip the leading double quote character.␊ |
774 | if (*ptr == '\"')␊ |
775 | {␊ |
776 | isQuoted = true;␊ |
777 | ptr++;␊ |
778 | strStart++;␊ |
779 | }␊ |
780 | ␊ |
781 | // Scan for the argument terminator character.␊ |
782 | // This can be either a NULL character - in case we reach the end of the string,␊ |
783 | // a double quote in case of quoted argument,␊ |
784 | // or a whitespace character (' ' or '=') for non-quoted argument.␊ |
785 | while (*ptr && !( (isQuoted && (*ptr == '\"')) ||␊ |
786 | (!isQuoted && (*ptr == ' ' || *ptr == '=')) )␊ |
787 | )␊ |
788 | {␊ |
789 | ptr++;␊ |
790 | }␊ |
791 | ␊ |
792 | len = ptr - strStart;␊ |
793 | ␊ |
794 | // Skip the closing double quote character and adjust␊ |
795 | // the starting pointer for the next getNextArg call.␊ |
796 | if (*ptr && isQuoted && *ptr == '\"')␊ |
797 | ptr++;␊ |
798 | ␊ |
799 | // Copy the extracted argument to val.␊ |
800 | strncat(val, strStart, len);␊ |
801 | ␊ |
802 | // Set command line pointer.␊ |
803 | *argPtr = ptr;␊ |
804 | ␊ |
805 | return ptr;␊ |
806 | }␊ |
807 | |