Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 721