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