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