Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/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 "libsaio.h"
30#include "bootstruct.h"
31#include "platform.h"
32#include "xml.h"
33
34static char * AllocInitStringWithLength(const char * oldString, int len);
35static char * AllocInitZeroEndedStringWithLength(const char * oldString, int len);
36
37#define ASSERT_CONFIG \
38if (config == DEFAULT_BOOT_CONFIG) \
39config = &bootInfo->bootConfig ; \
40else if (config == DEFAULT_SYSTEM_CONFIG) \
41config = &bootInfo->SystemConfig ; \
42else if (config == DEFAULT_OVERRIDE_CONFIG) \
43config = &bootInfo->overrideConfig ; \
44else if (config == DEFAULT_SMBIOS_CONFIG) \
45config = &bootInfo->smbiosConfig ; \
46else if (config == DEFAULT_HELPER_CONFIG) \
47config = &bootInfo->helperConfig ;
48
49#if UNUSED
50/*
51 * Compare a string to a key with quoted characters
52 */
53static inline int
54keyncmp(const char *str, const char *key, int n)
55{
56 int c;
57 while (n--) {
58c = *key++;
59if (c == '\\') {
60switch(c = *key++) {
61case 'n':
62c = '\n';
63break;
64case 'r':
65c = '\r';
66break;
67case 't':
68c = '\t';
69break;
70default:
71break;
72}
73} else if (c == '\"') {
74/* Premature end of key */
75return 1;
76}
77if (c != *str++) {
78return 1;
79}
80 }
81 return 0;
82}
83
84static void eatThru(char val, const char **table_p)
85{
86register const char *table = *table_p;
87register bool found = false;
88
89while (*table && !found)
90{
91if (*table == '\\') table += 2;
92else
93{
94if (*table == val) found = true;
95table++;
96}
97}
98*table_p = table;
99}
100
101/* Remove key and its associated value from the table. */
102
103bool
104removeKeyFromTable(const char *key, char *table)
105{
106 register int len;
107 register char *tab;
108 char *buf;
109
110 len = strlen(key);
111 tab = (char *)table;
112 buf = (char *)malloc(len + 3);
113
114 sprintf(buf, "\"%s\"", key);
115 len = strlen(buf);
116
117 while(*tab) {
118 if(strncmp(buf, tab, len) == 0) {
119 char c;
120
121 while((c = *(tab + len)) != ';') {
122 if(c == 0) {
123 len = -1;
124 goto out;
125 }
126 len++;
127 }
128 len++;
129 if(*(tab + len) == '\n') len++;
130 goto out;
131 }
132 tab++;
133 }
134 len = -1;
135out:
136 free(buf);
137
138 if(len == -1) return false;
139
140 while((*tab = *(tab + len))) {
141 tab++;
142 }
143
144 return true;
145}
146
147char *
148newStringFromList(
149 char **list,
150 int *size
151 )
152{
153 char *begin = *list, *end;
154 char *newstr;
155 int newsize = *size;
156 int bufsize;
157
158 while (*begin && newsize && isspace(*begin)) {
159begin++;
160newsize--;
161 }
162 end = begin;
163 while (*end && newsize && !isspace(*end)) {
164end++;
165newsize--;
166 }
167 if (begin == end)
168return 0;
169 bufsize = end - begin + 1;
170 newstr = malloc(bufsize);
171 strlcpy(newstr, begin, bufsize);
172 *list = end;
173 *size = newsize;
174 return newstr;
175}
176
177/*
178 * compress == compress escaped characters to one character
179 */
180int stringLength(const char *table, int compress)
181{
182int ret = 0;
183
184while (*table)
185{
186if (*table == '\\')
187{
188table += 2;
189ret += 1 + (compress ? 0 : 1);
190}
191else
192{
193if (*table == '\"') return ret;
194ret++;
195table++;
196}
197}
198return ret;
199}
200#endif
201
202bool getValueForConfigTableKey(config_file_t *config, const char *key, const char **val, int *size)
203{
204 ASSERT_CONFIG
205
206if (config->dictionary != 0 ) {
207// Look up key in XML dictionary
208TagPtr value;
209value = XMLGetProperty(config->dictionary, key);
210if (value != 0) {
211if (value->type != kTagTypeString) {
212error("Non-string tag '%s' found in config file\n",
213 key);
214return false;
215}
216*val = value->string;
217*size = strlen(value->string);
218return true;
219}
220} else {
221
222// Legacy plist-style table
223
224}
225
226return false;
227}
228
229#if UNUSED
230
231/*
232 * Returns a new malloc'ed string if one is found
233 * in the string table matching 'key'. Also translates
234 * \n escapes in the string.
235 */
236char *newStringForStringTableKey(
237 char *table,
238 char *key,
239 config_file_t *config
240 )
241{
242 const char *val;
243 char *newstr, *p;
244 int size;
245
246 ASSERT_CONFIG
247
248 if (getValueForConfigTableKey(config, key, &val, &size)) {
249newstr = (char *)malloc(size+1);
250for (p = newstr; size; size--, p++, val++) {
251if ((*p = *val) == '\\') {
252switch (*++val) {
253case 'r':
254*p = '\r';
255break;
256case 'n':
257*p = '\n';
258break;
259case 't':
260*p = '\t';
261break;
262default:
263*p = *val;
264break;
265}
266size--;
267}
268}
269*p = '\0';
270return newstr;
271 } else {
272return 0;
273 }
274}
275
276#endif
277
278char *
279newStringForKey(char *key, config_file_t *config)
280{
281 const char *val;
282 char *newstr;
283 int size;
284
285 ASSERT_CONFIG
286
287 if (getValueForKey(key, &val, &size, config) && size) {
288newstr = (char *)malloc(size + 1);
289strlcpy(newstr, val, size + 1);
290return newstr;
291 } else {
292return 0;
293 }
294}
295
296/* parse a command line
297 * in the form: [<argument> ...] [<option>=<value> ...]
298 * both <option> and <value> must be either composed of
299 * non-whitespace characters, or enclosed in quotes.
300 */
301
302static const char *getToken(const char *line, const char **begin, int *len)
303{
304 if (*line == '\"') {
305*begin = ++line;
306while (*line && *line != '\"')
307line++;
308*len = line++ - *begin;
309 } else {
310*begin = line;
311while (*line && !isspace(*line) && *line != '=')
312line++;
313*len = line - *begin;
314 }
315 return line;
316}
317
318bool getValueForBootKey(const char *line, const char *match, const char **matchval, int *len)
319{
320 const char *key, *value;
321 int key_len, value_len;
322 bool retval = false;
323
324 while (*line) {
325/* look for keyword or argument */
326while (isspace(*line)) line++;
327
328/* now look for '=' or whitespace */
329line = getToken(line, &key, &key_len);
330/* line now points to '=' or space */
331if (*line && !isspace(*line)) {
332line = getToken(++line, &value, &value_len);
333} else {
334value = line;
335value_len = 0;
336}
337if ((strlen(match) == key_len)
338&& strncmp(match, key, key_len) == 0) {
339*matchval = value;
340*len = value_len;
341retval = true;
342 /* Continue to look for this key; last one wins. */
343}
344 }
345 return retval;
346}
347
348/* Return NULL if no option has been successfully retrieved, or the string otherwise */
349const char * getStringForKey(const char * key, config_file_t *config)
350{
351static const char* value =0;
352int len=0;
353
354 ASSERT_CONFIG
355
356if(!getValueForKey(key, &value, &len, config)) value = 0;
357return value;
358}
359
360
361/* Returns TRUE if a value was found, FALSE otherwise.
362 * The boolean value of the key is stored in 'val'.
363 */
364
365bool getBoolForKey( const char *key, bool *result_val, config_file_t *config )
366{
367 const char *key_val;
368 int size;
369
370 ASSERT_CONFIG
371
372 if (getValueForKey(key, &key_val, &size, config)) {
373 if ( (size >= 1) && (key_val[0] == 'Y' || key_val[0] == 'y') ) {
374 *result_val = true;
375 } else {
376 *result_val = false;
377 }
378 return true;
379 }
380 return false;
381}
382
383bool getIntForKey( const char *key, int *value, config_file_t *config )
384{
385 const char *val;
386 int size, sum;
387 bool negative = false;
388
389 ASSERT_CONFIG
390
391 if (getValueForKey(key, &val, &size, config))
392{
393if ( size )
394{
395if (*val == '-')
396{
397negative = true;
398val++;
399size--;
400}
401
402for (sum = 0; size > 0; size--)
403{
404if (*val < '0' || *val > '9')
405return false;
406
407sum = (sum * 10) + (*val++ - '0');
408}
409
410if (negative)
411sum = -sum;
412
413*value = sum;
414return true;
415}
416}
417 return false;
418}
419
420/*
421 *
422 */
423
424bool getDimensionForKey( const char *key, unsigned int *value, config_file_t *config, unsigned int dimension_max, unsigned int object_size )
425{
426const char *val;
427
428 int size = 0;
429int sum = 0;
430
431bool negative = false;
432bool percentage = false;
433
434 ASSERT_CONFIG
435
436 if (getValueForKey(key, &val, &size, config))
437{
438if ( size )
439{
440if (*val == '-')
441{
442negative = true;
443val++;
444size--;
445}
446
447if (val[size-1] == '%')
448{
449percentage = true;
450size--;
451}
452
453// convert string to integer
454for (sum = 0; size > 0; size--)
455{
456if (*val < '0' || *val > '9')
457return false;
458
459sum = (sum * 10) + (*val++ - '0');
460}
461
462if (percentage)
463sum = ( dimension_max * sum ) / 100;
464
465// calculate offset from opposite origin
466if (negative)
467sum = ( ( dimension_max - object_size ) - sum );
468
469} else {
470
471// null value calculate center
472sum = ( dimension_max - object_size ) / 2;
473
474}
475
476*value = (uint16_t) sum;
477return true;
478}
479
480// key not found
481 return false;
482}
483
484/*
485 *get color value from plist format #RRGGBB
486 */
487
488bool getColorForKey( const char *key, unsigned int *value, config_file_t *config )
489{
490 const char *val;
491 int size;
492
493 ASSERT_CONFIG
494
495 if (getValueForKey(key, &val, &size, config))
496{
497if (*val == '#')
498{
499 val++;
500*value = strtol(val, NULL, 16);
501return true;
502 }
503 }
504 return false;
505}
506
507bool getValueForKey( const char *key, const char **val, int *size, config_file_t *config )
508{
509 const char *overrideVal;
510 int overrideSize;
511 bool ret;
512
513 if (getValueForBootKey(bootArgs->CommandLine, key, val, size))
514 return true;
515
516 ASSERT_CONFIG
517
518 ret = getValueForConfigTableKey(config, key, val, size);
519
520 // Try to find alternate keys in bootInfo->overrideConfig
521 // and prefer its values with the exceptions for
522 // "Kernel"="mach_kernel" and "Kernel Flags"="".
523
524 if (config->canOverride)
525 {
526 if (getValueForConfigTableKey(&bootInfo->overrideConfig, key, &overrideVal, &overrideSize) && overrideSize)
527 {
528 *val = overrideVal;
529 *size = overrideSize;
530 return true;
531 }
532 else if (getValueForConfigTableKey(&bootInfo->SystemConfig, key, &overrideVal, &overrideSize) && overrideSize)
533 {
534 *val = overrideVal;
535 *size = overrideSize;
536 return true;
537 }
538 }
539
540 return ret;
541}
542
543
544#if UNUSED
545void
546printSystemConfig(char *p1)
547{
548 char *p2 = p1, tmp;
549
550 while (*p1 != '\0') {
551while (*p2 != '\0' && *p2 != '\n') p2++;
552tmp = *p2;
553*p2 = '\0';
554printf("%s\n", p1);
555*p2 = tmp;
556if (tmp == '\0') break;
557p1 = ++p2;
558 }
559}
560#endif
561
562//==========================================================================
563// ParseXMLFile
564// Modifies the input buffer.
565// Expects to see one dictionary in the XML file.
566// Puts the first dictionary it finds in the
567// tag pointer and returns 0, or returns -1 if not found
568// (and does not modify dict pointer).
569// Prints an error message if there is a parsing error.
570//
571int ParseXMLFile( char * buffer, TagPtr * dict )
572{
573 long length, pos;
574 TagPtr tag;
575 pos = 0;
576 char *configBuffer;
577
578 configBuffer = malloc(strlen(buffer)+1);
579 strcpy(configBuffer, buffer);
580
581 while (1)
582 {
583 length = XMLParseNextTag(configBuffer + pos, &tag);
584 if (length == -1) break;
585
586 pos += length;
587
588 if (tag == 0) continue;
589 if (tag->type == kTagTypeDict) break;
590
591 XMLFreeTag(tag);
592 }
593 free(configBuffer);
594 if (length < 0) {
595 error ("Error parsing plist file\n");
596 return -1;
597 }
598 *dict = tag;
599 return 0;
600}
601
602/* loadConfigFile
603 *
604 * Returns 0 - successful.
605 * -1 - unsuccesful.
606 */
607int loadConfigFile (const char *configFile, config_file_t *config)
608{
609int fd, count;
610
611 ASSERT_CONFIG
612
613if ((fd = open(configFile)) < 0) {
614return -1;
615}
616
617// read file
618count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
619close(fd);
620
621// build xml dictionary
622return ParseXMLFile(config->plist, &config->dictionary);
623}
624
625/* loadBooterConfig
626 *
627 * Returns 0 - successful.
628 * -1 - unsuccesful.
629 */
630int loadBooterConfig(void)
631{
632char *dirspec[] = {
633"rd(0,0)/Extra/com.apple.Boot.plist",
634"/Extra/com.apple.Boot.plist",
635"bt(0,0)/Extra/com.apple.Boot.plist",
636"rd(0,0)/Extra/org.chameleon.Boot.plist", // Add compatibility with the trunk
637"/Extra/org.chameleon.Boot.plist", // Add compatibility with the trunk
638"bt(0,0)/Extra/org.chameleon.Boot.plist" // Add compatibility with the trunk
639
640
641};
642
643 config_file_t *config = &bootInfo->bootConfig;
644
645int i,fd, count, ret=-1;
646
647for(i = 0; (unsigned)i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
648{
649if ((fd = open(dirspec[i])) >= 0)
650{
651// read file
652count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
653close(fd);
654
655// build xml dictionary
656ParseXMLFile(config->plist, &config->dictionary);
657 safe_set_env(envSysConfigValid,true);
658ret=0;
659
660// enable canOverride flag
661config->canOverride = true;
662
663break;
664}
665}
666#ifdef BOOT_HELPER_SUPPORT
667if(ret == -1)
668{
669ret = loadHelperConfig();
670}
671#endif
672
673return ret;
674}
675
676/* loadOverrideConfig
677 *
678 * Returns 0 - successful.
679 * -1 - unsuccesful.
680 */
681int loadOverrideConfig(void)
682{
683char *dirspec[] = {
684"/Extra/com.apple.Boot.plist",
685"/Extra/org.chameleon.Boot.plist"
686};
687
688 config_file_t *config = &bootInfo->overrideConfig;
689
690
691int i,fd, count, ret=-1;
692
693for(i = 0; (unsigned)i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
694{
695if ((fd = open(dirspec[i])) >= 0)
696{
697// read file
698count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
699close(fd);
700
701// build xml dictionary
702ParseXMLFile(config->plist, &config->dictionary);
703 safe_set_env(envSysConfigValid,true);
704ret=0;
705break;
706}
707}
708#ifdef BOOT_HELPER_SUPPORT
709if(ret == -1)
710{
711ret = loadHelperConfig();
712}
713#endif
714
715return ret;
716}
717
718/* loadSystemConfig
719 *
720 * Returns 0 - successful.
721 * -1 - unsuccesful.
722 */
723int loadSystemConfig(void)
724{
725char *dirspec[] = {
726 "rd(0,0)/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
727"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
728"bt(0,0)/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
729 "rd(0,0)/Mac OS X Install Data/com.apple.Boot.plist",
730"/Mac OS X Install Data/com.apple.Boot.plist",
731"bt(0,0)/Mac OS X Install Data/com.apple.Boot.plist"
732};
733
734 config_file_t *config = &bootInfo->SystemConfig;
735
736
737int i,fd, count, ret=-1;
738
739for(i = 0; (unsigned)i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
740{
741if ((fd = open(dirspec[i])) >= 0)
742{
743// read file
744count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
745close(fd);
746
747// build xml dictionary
748ParseXMLFile(config->plist, &config->dictionary);
749 safe_set_env(envSysConfigValid,true);
750ret=0;
751break;
752}
753}
754
755return ret;
756}
757
758#ifdef BOOT_HELPER_SUPPORT
759
760/* loadHelperConfig
761 *
762 * Returns 0 - successful.
763 * -1 - unsuccesful.
764 */
765int loadHelperConfig(void)
766{
767int rfd, pfd, sfd, count, ret=-1;
768
769char *dirspec[] = {
770"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
771"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
772"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
773};
774
775 config_file_t *config = &bootInfo->helperConfig;
776
777
778// This is a simple rock - paper scissors algo. R beats S, P beats R, S beats P
779// If all three, S is used for now. This should be change dto something else (say, timestamp?)
780
781pfd = open(dirspec[0]);
782if(pfd >= 0)// com.apple.boot.P exists
783{
784sfd = open(dirspec[2]); // com.apple.boot.S takes precidence if it also exists
785if(sfd >= 0)
786{
787// Use sfd
788count = read(sfd, config->plist, IO_CONFIG_DATA_SIZE);
789close(sfd);
790close(pfd);
791
792// build xml dictionary
793ParseXMLFile(config->plist, &config->dictionary);
794 safe_set_env(envSysConfigValid,true);
795ret=0;
796
797}
798else
799{
800// used pfd
801count = read(pfd, config->plist, IO_CONFIG_DATA_SIZE);
802close(pfd);
803
804// build xml dictionary
805ParseXMLFile(config->plist, &config->dictionary);
806 safe_set_env(envSysConfigValid,true);
807ret=0;
808}
809
810}
811else
812{
813rfd = open(dirspec[1]); // com.apple.boot.R exists
814if(rfd >= 0)
815{
816pfd = open(dirspec[2]); // com.apple.boot.P takes recidence if it exists
817if(pfd >= 0)
818{
819// use sfd
820count = read(pfd, config->plist, IO_CONFIG_DATA_SIZE);
821close(pfd);
822close(rfd);
823
824// build xml dictionary
825ParseXMLFile(config->plist, &config->dictionary);
826 safe_set_env(envSysConfigValid,true);
827ret=0;
828
829}
830else
831{
832// use rfd
833count = read(rfd, config->plist, IO_CONFIG_DATA_SIZE);
834close(rfd);
835
836// build xml dictionary
837ParseXMLFile(config->plist, &config->dictionary);
838 safe_set_env(envSysConfigValid,true);
839ret=0;
840
841}
842
843}
844else
845{
846sfd = open(dirspec[2]); // com.apple.boot.S exists, but nothing else does
847if(sfd >= 0)
848{
849// use sfd
850count = read(sfd, config->plist, IO_CONFIG_DATA_SIZE);
851close(sfd);
852
853// build xml dictionary
854ParseXMLFile(config->plist, &config->dictionary);
855 safe_set_env(envSysConfigValid,true);
856ret=0;
857
858}
859}
860
861}
862
863return ret;
864}
865#endif
866
867static char * AllocInitStringWithLength(const char * oldString, int len)
868{
869char *Buf = NULL;
870Buf = malloc(len);
871if (Buf == NULL) return NULL;
872
873if (oldString != NULL)
874strlcpy(Buf, oldString,len);
875
876return Buf;
877}
878
879static char * AllocInitZeroEndedStringWithLength(const char * oldString, int len)
880{
881if (len > 0)
882{
883return AllocInitStringWithLength( oldString, len + 1);
884}
885return NULL;
886}
887
888char * newString(const char * oldString)
889{
890 if ( oldString )
891{
892int len = strlen(oldString);
893
894if (len > 0)
895{
896return AllocInitZeroEndedStringWithLength(oldString, len);
897}
898}
899 return NULL;
900}
901
902char * newStringWithLength(const char * oldString, int len)
903{
904if (len > 0)
905{
906return AllocInitZeroEndedStringWithLength(oldString, len);
907}
908 return NULL;
909}
910
911char * newEmptyStringWithLength(int len)
912{
913if (len > 0)
914{
915return AllocInitZeroEndedStringWithLength(NULL, len);
916}
917 return NULL;
918}
919
920/*
921 * Extracts the next argument from the command line, double quotes are allowed here.
922 */
923char * getNextArg(char ** argPtr, char * val)
924{
925char * ptr = *argPtr;
926const char * strStart;
927int len = 0;
928bool isQuoted = false;
929
930*val = '\0';
931
932// Scan for the next non-whitespace character.
933while ( *ptr && (*ptr == ' ' || *ptr == '=') )
934{
935ptr++;
936}
937
938strStart = ptr;
939
940// Skip the leading double quote character.
941if (*ptr == '\"')
942{
943isQuoted = true;
944ptr++;
945strStart++;
946}
947
948// Scan for the argument terminator character.
949// This can be either a NULL character - in case we reach the end of the string,
950// a double quote in case of quoted argument,
951// or a whitespace character (' ' or '=') for non-quoted argument.
952while (*ptr && !( (isQuoted && (*ptr == '\"')) ||
953 (!isQuoted && (*ptr == ' ' || *ptr == '=')) )
954 )
955{
956ptr++;
957}
958
959len = ptr - strStart;
960
961// Skip the closing double quote character and adjust
962// the starting pointer for the next getNextArg call.
963if (*ptr && isQuoted && *ptr == '\"')
964ptr++;
965
966// Copy the extracted argument to val.
967strncat(val, strStart, len);
968
969// Set command line pointer.
970*argPtr = ptr;
971
972return ptr;
973}
974

Archive Download this file

Revision: 1899