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

Archive Download this file

Revision: 2042