Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Trunk/i386/libsaio/stringTable.c

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
32extern char *Language;
33extern char *LoadableFamilies;
34
35bool sysConfigValid;
36
37/*
38 * Compare a string to a key with quoted characters
39 */
40static inline int
41keyncmp(const char *str, const char *key, int n)
42{
43 int c;
44 while (n--) {
45c = *key++;
46if (c == '\\') {
47 switch(c = *key++) {
48 case 'n':
49c = '\n';
50break;
51 case 'r':
52c = '\r';
53break;
54 case 't':
55c = '\t';
56break;
57 default:
58break;
59 }
60} else if (c == '\"') {
61 /* Premature end of key */
62 return 1;
63}
64if (c != *str++) {
65 return 1;
66}
67 }
68 return 0;
69}
70
71#if UNUSED
72
73static void eatThru(char val, const char **table_p)
74{
75register const char *table = *table_p;
76register bool found = false;
77
78while (*table && !found)
79{
80if (*table == '\\') table += 2;
81else
82{
83if (*table == val) found = true;
84table++;
85}
86}
87*table_p = table;
88}
89
90/* Remove key and its associated value from the table. */
91
92bool
93removeKeyFromTable(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;
124out:
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
136char *newStringFromList(char **list, int *size)
137{
138char *begin = *list, *end;
139char *newstr;
140int newsize = *size;
141int bufsize;
142
143while (*begin && newsize && isspace(*begin))
144{
145begin++;
146newsize--;
147}
148end = begin;
149while (*end && newsize && !isspace(*end))
150{
151end++;
152newsize--;
153}
154if (begin == end)
155{
156return 0;
157}
158bufsize = end - begin + 1;
159newstr = malloc(bufsize);
160strlcpy(newstr, begin, bufsize);
161*list = end;
162*size = newsize;
163return newstr;
164}
165
166#endif
167
168/*
169 * compress == compress escaped characters to one character
170 */
171int stringLength(const char *table, int compress)
172{
173int ret = 0;
174
175while (*table)
176{
177if (*table == '\\')
178{
179table += 2;
180ret += 1 + (compress ? 0 : 1);
181}
182else
183{
184if (*table == '\"') return ret;
185ret++;
186table++;
187}
188}
189return ret;
190}
191
192
193bool getValueForConfigTableKey(config_file_t *config, const char *key, const char **val, int *size)
194{
195if (config->dictionary != 0 )
196{
197// Look up key in XML dictionary
198TagPtr value;
199value = XMLGetProperty(config->dictionary, key);
200if (value != 0)
201{
202if (value->type != kTagTypeString)
203{
204error("Non-string tag '%s' found in config file\n", key);
205return false;
206}
207*val = value->string;
208*size = strlen(value->string);
209return true;
210}
211}
212else
213{
214
215// Legacy plist-style table
216
217}
218
219return 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 */
229char *newStringForStringTableKey(char *table, char *key, config_file_t *config)
230{
231const char *val;
232char *newstr, *p;
233int size;
234
235if (getValueForConfigTableKey(config, key, &val, &size))
236{
237newstr = (char *)malloc(size+1);
238for (p = newstr; size; size--, p++, val++)
239{
240if ((*p = *val) == '\\')
241{
242switch (*++val)
243{
244case 'r':
245*p = '\r';
246break;
247case 'n':
248*p = '\n';
249break;
250case 't':
251*p = '\t';
252break;
253default:
254*p = *val;
255break;
256}
257size--;
258}
259}
260*p = '\0';
261return newstr;
262}
263else
264{
265return 0;
266}
267}
268
269#endif
270
271char *
272newStringForKey(char *key, config_file_t *config)
273{
274const char *val;
275char *newstr;
276int size;
277
278if (getValueForKey(key, &val, &size, config) && size)
279{
280newstr = (char *)malloc(size + 1);
281strlcpy(newstr, val, size + 1);
282return newstr;
283}
284else
285{
286return 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
296static const char *getToken(const char *line, const char **begin, int *len)
297{
298 if (*line == '\"') {
299*begin = ++line;
300while (*line && *line != '\"')
301 line++;
302*len = line++ - *begin;
303 } else {
304*begin = line;
305while (*line && !isspace(*line) && *line != '=')
306 line++;
307*len = line - *begin;
308 }
309 return line;
310}
311
312bool 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 */
320while (isspace(*line)) line++;
321
322/* now look for '=' or whitespace */
323line = getToken(line, &key, &key_len);
324/* line now points to '=' or space */
325if (*line && !isspace(*line)) {
326 line = getToken(++line, &value, &value_len);
327} else {
328 value = line;
329 value_len = 0;
330}
331if ((strlen(match) == key_len)
332 && strncmp(match, key, key_len) == 0) {
333// create a new string
334char* newstr = malloc(value_len + 1);
335strncpy(newstr, value, value_len);
336newstr[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 */
350const 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
363bool 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
379bool 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{
387if ( size )
388{
389if (*val == '-')
390{
391negative = true;
392val++;
393size--;
394}
395
396for (sum = 0; size > 0; size--)
397{
398if (*val < '0' || *val > '9')
399return false;
400
401sum = (sum * 10) + (*val++ - '0');
402}
403
404if (negative)
405sum = -sum;
406
407*value = sum;
408return true;
409}
410}
411 return false;
412}
413
414/*
415 *
416 */
417
418bool getDimensionForKey( const char *key, unsigned int *value, config_file_t *config, unsigned int dimension_max, unsigned int object_size )
419{
420const char *val;
421
422 int size = 0;
423int sum = 0;
424
425bool negative = false;
426bool percentage = false;
427
428 if (getValueForKey(key, &val, &size, config))
429{
430if ( size )
431{
432if (*val == '-')
433{
434negative = true;
435val++;
436size--;
437}
438
439if (val[size-1] == '%')
440{
441percentage = true;
442size--;
443}
444
445// convert string to integer
446for (sum = 0; size > 0; size--)
447{
448if (*val < '0' || *val > '9')
449return false;
450
451sum = (sum * 10) + (*val++ - '0');
452}
453
454if (percentage)
455sum = ( dimension_max * sum ) / 100;
456
457// calculate offset from opposite origin
458if (negative)
459sum = ( ( dimension_max - object_size ) - sum );
460
461} else {
462
463// null value calculate center
464sum = ( dimension_max - object_size ) / 2;
465
466}
467
468*value = (uint16_t) sum;
469return true;
470}
471
472// key not found
473 return false;
474}
475
476/*
477 *get color value from plist format #RRGGBB
478 */
479
480bool 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{
487if (*val == '#')
488{
489 val++;
490*value = strtol(val, NULL, 16);
491return true;
492 }
493 }
494 return false;
495}
496
497bool 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
540void
541printSystemConfig(char *p1)
542{
543 char *p2 = p1, tmp;
544
545 while (*p1 != '\0') {
546while (*p2 != '\0' && *p2 != '\n') p2++;
547tmp = *p2;
548*p2 = '\0';
549printf("%s\n", p1);
550*p2 = tmp;
551if (tmp == '\0') break;
552p1 = ++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//
566int 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 */
602int loadConfigFile (const char *configFile, config_file_t *config)
603{
604int fd, count;
605
606if ((fd = open_bvdev("bt(0,0)", configFile, 0)) < 0) {
607return -1;
608}
609// read file
610count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
611close(fd);
612
613// build xml dictionary
614ParseXMLFile(config->plist, &config->dictionary);
615return 0;
616}
617
618
619/* loadSystemConfig
620 *
621 * Returns 0 - successful.
622 * -1 - unsuccesful.
623 */
624int loadSystemConfig(config_file_t *config)
625{
626char *dirspec[] = {
627"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
628};
629
630int i, fd, count, ret=-1;
631
632for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
633{
634if ((fd = open(dirspec[i], 0)) >= 0)
635{
636// read file
637count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
638close(fd);
639
640// build xml dictionary
641ParseXMLFile(config->plist, &config->dictionary);
642sysConfigValid = true;
643ret=0;
644
645break;
646}
647}
648
649if(ret == -1) ret = loadHelperConfig(config);
650
651// Always enable canOverride flag (for SystemConfig)
652config->canOverride = true;
653
654return ret;
655}
656
657/* loadChameleonConfig
658 *
659 * Returns 0 - successful.
660 * -1 - unsuccesful.
661 */
662int loadChameleonConfig(config_file_t *config)
663{
664char *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
674int i, fd, count, ret=-1;
675
676for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
677{
678if ((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
689count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
690close(fd);
691
692// build xml dictionary
693ParseXMLFile(config->plist, &config->dictionary);
694sysConfigValid = true;
695ret=0;
696break;
697}
698}
699return ret;
700}
701
702/* loadHelperConfig
703 *
704 * Returns 0 - successful.
705 * -1 - unsuccesful.
706 */
707int loadHelperConfig(config_file_t *config)
708{
709char *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
715int i, fd, count, ret=-1;
716
717for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
718{
719if ((fd = open(dirspec[i], 0)) >= 0)
720{
721// read file
722count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
723close(fd);
724
725// build xml dictionary
726ParseXMLFile(config->plist, &config->dictionary);
727sysConfigValid = true;
728ret=0;
729break;
730}
731}
732return ret;
733}
734
735char * 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 */
746char * 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

Archive Download this file

Revision: 2037