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