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