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