Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 1