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

Archive Download this file

Revision: 459