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

Archive Download this file

Revision: 1804