Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazileon/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/*
25 * Copyright 1993 NeXT, Inc.
26 * All rights reserved.
27 */
28
29#include "bootstruct.h"
30#include "libsaio.h"
31#include "xml.h"
32#include "boot.h" //Azi:canoverride, gMacOSVersion
33#include "ramdisk.h" //Azi:searchalgo
34
35extern char *Language;
36extern char *LoadableFamilies;
37
38bool sysConfigValid;
39
40/*
41 * Compare a string to a key with quoted characters
42 */
43static inline int
44keyncmp(const char *str, const char *key, int n)
45{
46 int c;
47 while (n--) {
48c = *key++;
49if (c == '\\') {
50 switch(c = *key++) {
51 case 'n':
52c = '\n';
53break;
54 case 'r':
55c = '\r';
56break;
57 case 't':
58c = '\t';
59break;
60 default:
61break;
62 }
63} else if (c == '\"') {
64 /* Premature end of key */
65 return 1;
66}
67if (c != *str++) {
68 return 1;
69}
70 }
71 return 0;
72}
73
74#if UNUSED
75
76static void eatThru(char val, const char **table_p)
77{
78register const char *table = *table_p;
79register bool found = false;
80
81while (*table && !found)
82{
83if (*table == '\\') table += 2;
84else
85{
86if (*table == val) found = true;
87table++;
88}
89}
90*table_p = table;
91}
92
93/* Remove key and its associated value from the table. */
94
95bool
96removeKeyFromTable(const char *key, char *table)
97{
98 register int len;
99 register char *tab;
100 char *buf;
101
102 len = strlen(key);
103 tab = (char *)table;
104 buf = (char *)malloc(len + 3);
105
106 sprintf(buf, "\"%s\"", key);
107 len = strlen(buf);
108
109 while(*tab) {
110 if(strncmp(buf, tab, len) == 0) {
111 char c;
112
113 while((c = *(tab + len)) != ';') {
114 if(c == 0) {
115 len = -1;
116 goto out;
117 }
118 len++;
119 }
120 len++;
121 if(*(tab + len) == '\n') len++;
122 goto out;
123 }
124 tab++;
125 }
126 len = -1;
127out:
128 free(buf);
129
130 if(len == -1) return false;
131
132 while((*tab = *(tab + len))) {
133 tab++;
134 }
135
136 return true;
137}
138
139char *
140newStringFromList(
141 char **list,
142 int *size
143)
144{
145 char *begin = *list, *end;
146 char *newstr;
147 int newsize = *size;
148 int bufsize;
149
150 while (*begin && newsize && isspace(*begin)) {
151begin++;
152newsize--;
153 }
154 end = begin;
155 while (*end && newsize && !isspace(*end)) {
156end++;
157newsize--;
158 }
159 if (begin == end)
160return 0;
161 bufsize = end - begin + 1;
162 newstr = malloc(bufsize);
163 strlcpy(newstr, begin, bufsize);
164 *list = end;
165 *size = newsize;
166 return newstr;
167}
168
169#endif
170
171/*
172 * compress == compress escaped characters to one character
173 */
174int stringLength(const char *table, int compress)
175{
176int ret = 0;
177
178while (*table)
179{
180if (*table == '\\')
181{
182table += 2;
183ret += 1 + (compress ? 0 : 1);
184}
185else
186{
187if (*table == '\"') return ret;
188ret++;
189table++;
190}
191}
192return ret;
193}
194
195
196bool getValueForConfigTableKey(config_file_t *config, const char *key, const char **val, int *size)
197{
198if (config->dictionary != 0)
199{
200// Look up key in XML dictionary
201TagPtr value;
202value = XMLGetProperty(config->dictionary, key);
203if (value != 0)
204{
205if (value->type != kTagTypeString)
206{
207error("Non-string tag '%s' found in config file\n", key);
208return false;
209}
210
211*val = value->string;
212*size = strlen(value->string);
213return true;
214}
215}
216else
217{
218// Legacy plist-style table Azi:??
219}
220return false;
221}
222
223#if UNUSED
224
225/*
226 * Returns a new malloc'ed string if one is found
227 * in the string table matching 'key'. Also translates
228 * \n escapes in the string.
229 */
230char *newStringForStringTableKey(
231char *table,
232char *key,
233config_file_t *config
234)
235{
236 const char *val;
237 char *newstr, *p;
238 int size;
239
240 if (getValueForConfigTableKey(config, key, &val, &size)) {
241newstr = (char *)malloc(size+1);
242for (p = newstr; size; size--, p++, val++) {
243 if ((*p = *val) == '\\') {
244switch (*++val) {
245case 'r':
246 *p = '\r';
247 break;
248case 'n':
249 *p = '\n';
250 break;
251case 't':
252 *p = '\t';
253 break;
254default:
255 *p = *val;
256 break;
257}
258size--;
259 }
260}
261*p = '\0';
262return newstr;
263 } else {
264return 0;
265 }
266}
267
268#endif
269
270char *
271newStringForKey(char *key, config_file_t *config)
272{
273 const char *val;
274 char *newstr;
275 int size;
276
277 if (getValueForKey(key, &val, &size, config) && size) {
278newstr = (char *)malloc(size + 1);
279strlcpy(newstr, val, size + 1);
280return newstr;
281 } else {
282return 0;
283 }
284}
285
286/* parse a command line
287 * in the form: [<argument> ...] [<option>=<value> ...]
288 * both <option> and <value> must be either composed of
289 * non-whitespace characters, or enclosed in quotes.
290 */
291
292static const char *getToken(const char *line, const char **begin, int *len)
293{
294 if (*line == '\"') {
295*begin = ++line;
296while (*line && *line != '\"')
297 line++;
298*len = line++ - *begin;
299 } else {
300*begin = line;
301while (*line && !isspace(*line) && *line != '=')
302 line++;
303*len = line - *begin;
304 }
305 return line;
306}
307
308bool getValueForBootKey(const char *line, const char *match, const char **matchval, int *len)
309{
310 const char *key, *value;
311 int key_len, value_len;
312 bool retval = false;
313
314 while (*line)
315{
316// look for keyword or argument
317while (isspace(*line)) line++;
318
319// now look for '=' or whitespace
320line = getToken(line, &key, &key_len);
321// line now points to '=' or space
322if (*line && !isspace(*line))
323{
324line = getToken(++line, &value, &value_len);
325}
326else
327{
328value = line;
329value_len = 0;
330}
331
332if ((strlen(match) == key_len) && strncmp(match, key, key_len) == 0)
333{
334*matchval = value;
335*len = value_len;
336retval = true;
337 /* Continue to look for this key; last one wins. */
338}
339 }
340 return retval;
341}
342
343/* Return NULL if no option has been successfully retrieved, or the string otherwise */
344const char * getStringForKey(const char * key, config_file_t *config)
345{
346 static const char* value =0;
347 int len=0;
348 if(!getValueForKey(key, &value, &len, config)) value = 0;
349 return value;
350}
351
352
353/* Returns TRUE if a value was found, FALSE otherwise.
354 * The boolean value of the key is stored in 'val'.
355 */
356
357bool getBoolForKey( const char *key, bool *result_val, config_file_t *config )
358{
359 const char *key_val;
360 int size;
361
362 if (getValueForKey(key, &key_val, &size, config)) {
363 if ( (size >= 1) && (key_val[0] == 'Y' || key_val[0] == 'y') ) {
364 *result_val = true;
365 } else {
366 *result_val = false;
367 }
368 return true;
369 }
370 return false;
371}
372
373bool getIntForKey( const char *key, int *value, config_file_t *config )
374{
375 const char *val;
376 int size, sum;
377 bool negative = false;
378
379 if (getValueForKey(key, &val, &size, config))
380{
381if ( size )
382{
383if (*val == '-')
384{
385negative = true;
386val++;
387size--;
388}
389
390for (sum = 0; size > 0; size--)
391{
392if (*val < '0' || *val > '9')
393return false;
394
395sum = (sum * 10) + (*val++ - '0');
396}
397
398if (negative)
399sum = -sum;
400
401*value = sum;
402return true;
403}
404}
405 return false;
406}
407
408/*
409 *
410 */
411
412bool getDimensionForKey( const char *key, unsigned int *value, config_file_t *config, unsigned int dimension_max, unsigned int object_size )
413{
414const char *val;
415
416 int size = 0;
417int sum = 0;
418
419bool negative = false;
420bool percentage = false;
421
422 if (getValueForKey(key, &val, &size, config))
423{
424if ( size )
425{
426if (*val == '-')
427{
428negative = true;
429val++;
430size--;
431}
432
433if (val[size-1] == '%')
434{
435percentage = true;
436size--;
437}
438
439// convert string to integer
440for (sum = 0; size > 0; size--)
441{
442if (*val < '0' || *val > '9')
443return false;
444
445sum = (sum * 10) + (*val++ - '0');
446}
447
448if (percentage)
449sum = ( dimension_max * sum ) / 100;
450
451// calculate offset from opposite origin
452if (negative)
453sum = ( ( dimension_max - object_size ) - sum );
454
455} else {
456
457// null value calculate center
458sum = ( dimension_max - object_size ) / 2;
459
460}
461
462*value = (uint16_t) sum;
463return true;
464}
465
466// key not found
467 return false;
468}
469
470/*
471 *get color value from plist format #RRGGBB
472 */
473
474bool getColorForKey( const char *key, unsigned int *value, config_file_t *config )
475{
476 const char *val;
477 int size;
478
479 if (getValueForKey(key, &val, &size, config))
480{
481if (*val == '#')
482{
483 val++;
484*value = strtol(val, NULL, 16);
485return true;
486 }
487 }
488 return false;
489}
490
491bool getValueForKey( const char *key, const char **val, int *size, config_file_t *config )
492{
493const char *overrideVal;
494int overrideSize;
495bool override, ret;
496
497if (getValueForBootKey(bootArgs->CommandLine, key, val, size))
498return true;
499
500ret = getValueForConfigTableKey(config, key, val, size);
501
502// Try to find alternate keys in bootInfo->overrideConfig and prefer its values
503// with the exceptions for "Kernel"="mach_kernel" and "Kernel Flags"="".
504if (config->canOverride)
505{
506if (getValueForConfigTableKey(&bootInfo->overrideConfig, key, &overrideVal, &overrideSize))
507{
508override = true;
509//Azi: kKernelNameKey, kDefaultKernelk, KernelFlagsKey can be used if boot.h is included.
510if (ret && (strcmp(key, kKernelNameKey) == 0) && (strcmp(overrideVal, kDefaultKernelName) == 0))
511override = false;
512
513if (ret && (strcmp(key, kKernelFlagsKey) == 0) && (overrideSize == 0))
514override = false;
515
516if (override)
517{
518*val = overrideVal;
519*size = overrideSize;
520return true;
521}
522}
523}
524return ret;
525}
526
527
528#if UNUSED
529void
530printSystemConfig(char *p1)
531{
532 char *p2 = p1, tmp;
533
534 while (*p1 != '\0') {
535while (*p2 != '\0' && *p2 != '\n') p2++;
536tmp = *p2;
537*p2 = '\0';
538printf("%s\n", p1);
539*p2 = tmp;
540if (tmp == '\0') break;
541p1 = ++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//
555int 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 */
591int loadConfigFile(const char *configFile, config_file_t *config)
592{
593int fd, count;
594
595if ((fd = open_bvdev("bt(0,0)", configFile, 0)) < 0) {
596return -1;
597}
598// read file
599count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
600close(fd);
601
602// build xml dictionary
603ParseXMLFile(config->plist, &config->dictionary);
604return 0;
605}
606
607/* loadSystemConfig
608 *
609 * Returns 0 - successful.
610 * -1 - unsuccesful.
611 */
612int loadSystemConfig(config_file_t *config) //Azi:searchalgo???
613{
614char *dirspec[] = {
615//"/Extra/com.apple.Boot.plist", removed in favor of bt(0,0) - review? only needed to load it from selected volume.
616"bt(0,0)/Extra/com.apple.Boot.plist",
617"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
618"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
619"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
620"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
621};
622
623int i, fd, count, ret = -1;
624
625for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
626{
627if ((fd = open(dirspec[i], 0)) >= 0)
628{
629// read file
630count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
631close(fd);
632
633// build xml dictionary
634ParseXMLFile(config->plist, &config->dictionary);
635sysConfigValid = true;
636ret = 0;
637
638// enable canOverride flag
639config->canOverride = true;
640
641//Azi: disable canOverride. Remove?
642getBoolForKey(kCanOverrideKey, &config->canOverride, &bootInfo->bootConfig);
643
644break;
645}
646}
647return ret;
648}
649
650/* loadOverrideConfig
651 *
652 * Returns 0 - successful.
653 * -1 - unsuccesful.
654 */
655int loadOverrideConfig(config_file_t *config)
656{
657char dirSpecBplist[128] = "";
658const char*override_pathname = NULL;
659const char*filename = "com.apple.Boot.plist";
660int count, ret, fd, len = 0;
661
662// Take in account user overriding the override :P
663if (getValueForKey(kTestConfigKey, &override_pathname, &len, &bootInfo->bootConfig))
664{
665// Specify a path to a file, e.g. config=/Extra/test.plist
666strcpy(dirSpecBplist, override_pathname);
667fd = open(dirSpecBplist, 0);
668if (fd >= 0) goto success_fd;
669}
670
671// Check rd's root for override config.
672sprintf(dirSpecBplist, "rd(0,0)/%s", filename);
673fd = open(dirSpecBplist, 0);
674if (fd >= 0) goto success_fd;
675
676// Check OS specific folders.
677sprintf(dirSpecBplist, "bt(0,0)/Extra/%s/%s", &gMacOSVersion, filename);
678fd = open(dirSpecBplist, 0);
679//if (fd >= 0) goto success_fd;
680
681//Azi: i really don't like these two!
682// "/Extra/com.apple.Boot.plist"
683// "/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
684
685// These i have no way to test, need advice.
686// "/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist)
687// "/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist)
688// "/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist)
689
690success_fd:
691
692if (fd >= 0)
693{
694// read file
695count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
696close(fd);
697
698// build xml dictionary
699ParseXMLFile(config->plist, &config->dictionary);
700sysConfigValid = true;
701ret = 0;
702}
703else
704{
705printf("No override config provided!\n");
706ret = -1;
707}
708return ret;
709}
710
711/* loadHelperConfig
712 *
713 * Returns 0 - successful.
714 * -1 - unsuccesful.
715 *
716 */
717int loadHelperConfig(config_file_t *config)
718{
719//Azi: Called from options.c, processBootOptions (secondrun).
720// Seems to be used just to check plist for UUID key.
721char *dirspec[] = {
722"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
723"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
724"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
725};
726
727int i, fd, count, ret = -1;
728
729for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
730{
731if ((fd = open(dirspec[i], 0)) >= 0)
732{
733// read file
734count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
735close(fd);
736
737// build xml dictionary
738ParseXMLFile(config->plist, &config->dictionary);
739sysConfigValid = true;
740ret = 0;
741break;
742}
743}
744return ret;
745}
746
747char * newString(const char * oldString)
748{
749 if ( oldString )
750 return strcpy(malloc(strlen(oldString)+1), oldString);
751 else
752 return NULL;
753}
754
755/*
756 * Extracts the next argument from the command line, double quotes are allowed here.
757 */
758char * getNextArg(char ** argPtr, char * val)
759{
760 char * ptr = *argPtr;
761 const char * strStart;
762 int len = 0;
763 bool isQuoted = false;
764
765 *val = '\0';
766
767 // Scan for the next non-whitespace character.
768 while ( *ptr && (*ptr == ' ' || *ptr == '=') )
769 {
770 ptr++;
771 }
772
773 strStart = ptr;
774
775 // Skip the leading double quote character.
776 if (*ptr == '\"')
777 {
778 isQuoted = true;
779 ptr++;
780 strStart++;
781 }
782
783 // Scan for the argument terminator character.
784 // This can be either a NULL character - in case we reach the end of the string,
785 // a double quote in case of quoted argument,
786 // or a whitespace character (' ' or '=') for non-quoted argument.
787 while (*ptr && !( (isQuoted && (*ptr == '\"')) ||
788 (!isQuoted && (*ptr == ' ' || *ptr == '=')) )
789 )
790 {
791 ptr++;
792 }
793
794 len = ptr - strStart;
795
796 // Skip the closing double quote character and adjust
797 // the starting pointer for the next getNextArg call.
798 if (*ptr && isQuoted && *ptr == '\"')
799 ptr++;
800
801 // Copy the extracted argument to val.
802 strncat(val, strStart, len);
803
804 // Set command line pointer.
805 *argPtr = ptr;
806
807 return ptr;
808}
809

Archive Download this file

Revision: 399