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