Chameleon

Chameleon Svn Source Tree

Root/branches/rekursor/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/* Return NULL if no option has been successfully retrieved, or the string otherwise */
342const char * getStringForKey(const char * key, config_file_t *config)
343{
344 static const char* value =0;
345 int len=0;
346 if(getValueForKey(key, &value, &len, config)!=YES) value = 0;
347 return value;
348}
349
350/* Returns TRUE if a value was found, FALSE otherwise.
351 * The boolean value of the key is stored in 'val'.
352 */
353
354BOOL getBoolForKey( const char *key, BOOL *result_val, config_file_t *config )
355{
356 const char *key_val;
357 int size;
358
359 if (getValueForKey(key, &key_val, &size, config)) {
360 if ( (size >= 1) && (key_val[0] == 'Y' || key_val[0] == 'y') ) {
361 *result_val = YES;
362 } else {
363 *result_val = NO;
364 }
365 return YES;
366 }
367 return NO;
368}
369
370BOOL getIntForKey( const char *key, int *value, config_file_t *config )
371{
372 const char *val;
373 int size, sum;
374 BOOL negative = NO;
375
376 if (getValueForKey(key, &val, &size, config))
377{
378if ( size )
379{
380if (*val == '-')
381{
382negative = YES;
383val++;
384size--;
385}
386
387for (sum = 0; size > 0; size--)
388{
389if (*val < '0' || *val > '9')
390return NO;
391
392sum = (sum * 10) + (*val++ - '0');
393}
394
395if (negative)
396sum = -sum;
397
398*value = sum;
399return YES;
400}
401}
402 return NO;
403}
404
405/*
406 *
407 */
408
409BOOL getDimensionForKey( const char *key, unsigned int *value, config_file_t *config, unsigned int dimension_max, unsigned int object_size )
410{
411const char *val;
412
413 int size = 0;
414int sum = 0;
415
416BOOL negative = NO;
417BOOL percentage = NO;
418
419 if (getValueForKey(key, &val, &size, config))
420{
421if ( size )
422{
423if (*val == '-')
424{
425negative = YES;
426val++;
427size--;
428}
429
430if (val[size-1] == '%')
431{
432percentage = YES;
433size--;
434}
435
436// convert string to integer
437for (sum = 0; size > 0; size--)
438{
439if (*val < '0' || *val > '9')
440return NO;
441
442sum = (sum * 10) + (*val++ - '0');
443}
444
445if (percentage)
446sum = ( dimension_max * sum ) / 100;
447
448// calculate offset from opposite origin
449if (negative)
450sum = ( ( dimension_max - object_size ) - sum );
451
452} else {
453
454// null value calculate center
455sum = ( dimension_max - object_size ) / 2;
456
457}
458
459*value = (uint16_t) sum;
460return YES;
461}
462
463// key not found
464 return NO;
465}
466
467/*
468 *get color value from plist format #RRGGBB
469 */
470
471BOOL getColorForKey( const char *key, unsigned int *value, config_file_t *config )
472{
473 const char *val;
474 int size;
475
476 if (getValueForKey(key, &val, &size, config))
477{
478if (*val == '#')
479{
480 val++;
481*value = strtol(val, NULL, 16);
482return YES;
483 }
484 }
485 return NO;
486}
487
488BOOL getValueForKey( const char *key, const char **val, int *size, config_file_t *config )
489{
490 const char *overrideVal;
491 int overrideSize;
492 BOOL override, ret;
493
494 if (getValueForBootKey(bootArgs->CommandLine, key, val, size))
495 return YES;
496
497 ret = getValueForConfigTableKey(config, key, val, size);
498
499 // Try to find alternate keys in bootInfo->overrideConfig
500 // and prefer its values with the exceptions for
501 // "Kernel"="mach_kernel" and "Kernel Flags"="".
502
503 if (config->canOverride)
504 {
505 if (getValueForConfigTableKey(&bootInfo->overrideConfig, key, &overrideVal, &overrideSize))
506 {
507 override = YES;
508
509 if (ret && (strcmp(key, "Kernel") == 0) && (strcmp(overrideVal, "mach_kernel") == 0))
510 override = NO;
511
512 if (ret && (strcmp(key, "Kernel Flags") == 0) && (overrideSize == 0))
513 override = NO;
514
515 if (override)
516 {
517 *val = overrideVal;
518 *size = overrideSize;
519 return YES;
520 }
521 }
522 }
523
524 return ret;
525}
526
527
528#if UNUSED
529void
530printSystemConfig(char *p1)
531{
532 char *p2 = p1, tmp;
533
534 while (*p1 != '\0') {
535while (*p2 != '\0' && *p2 != '\n') p2++;
536tmp = *p2;
537*p2 = '\0';
538printf("%s\n", p1);
539*p2 = tmp;
540if (tmp == '\0') break;
541p1 = ++p2;
542 }
543}
544#endif
545
546//==========================================================================
547// ParseXMLFile
548// Modifies the input buffer.
549// Expects to see one dictionary in the XML file.
550// Puts the first dictionary it finds in the
551// tag pointer and returns 0, or returns -1 if not found
552// (and does not modify dict pointer).
553// Prints an error message if there is a parsing error.
554//
555long ParseXMLFile( char * buffer, TagPtr * dict )
556{
557 long length, pos;
558 TagPtr tag;
559 pos = 0;
560 char *configBuffer;
561
562 configBuffer = MALLOC(strlen(buffer)+1);
563 strcpy(configBuffer, buffer);
564
565 while (1)
566 {
567 length = XMLParseNextTag(configBuffer + pos, &tag);
568 if (length == -1) break;
569
570 pos += length;
571
572 if (tag == 0) continue;
573 if (tag->type == kTagTypeDict) break;
574
575 XMLFreeTag(tag);
576 }
577 free(configBuffer);
578 if (length < 0) {
579 error ("Error parsing plist file\n");
580 return -1;
581 }
582 *dict = tag;
583 return 0;
584}
585
586/* loadConfigFile
587 *
588 * Returns 0 - successful.
589 * -1 - unsuccesful.
590 */
591int loadConfigFile (const char *configFile, config_file_t *config)
592{
593int fd, count;
594char dirspec[512];
595
596sprintf(dirspec,"%s",configFile);
597fd = open(dirspec, 0);
598if (fd<0)
599{
600dirspec[0] = '\0';
601sprintf(dirspec,"bt(0,0)%s",configFile);
602fd = open(dirspec, 0);
603if (fd<0)
604return -1;
605}
606// read file
607count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
608close(fd);
609
610// build xml dictionary
611ParseXMLFile(config->plist, &config->dictionary);
612return 0;
613}
614
615
616/* loadSystemConfig
617 *
618 * Returns 0 - successful.
619 * -1 - unsuccesful.
620 */
621int loadSystemConfig(config_file_t *config)
622{
623char *dirspec[] = {
624"/Extra/com.apple.Boot.plist",
625"bt(0,0)/Extra/com.apple.Boot.plist",
626"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
627"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
628"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
629"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
630};
631
632int i, fd, count, ret=-1;
633
634for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
635{
636if ((fd = open(dirspec[i], 0)) >= 0)
637{
638// read file
639count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
640close(fd);
641
642// build xml dictionary
643ParseXMLFile(config->plist, &config->dictionary);
644sysConfigValid=1;
645ret=0;
646
647// enable canOverride flag
648config->canOverride = TRUE;
649
650break;
651}
652}
653return ret;
654}
655
656/* loadOverrideConfig
657 *
658 * Returns 0 - successful.
659 * -1 - unsuccesful.
660 */
661int loadOverrideConfig(config_file_t *config)
662{
663char *dirspec[] = {
664"rd(0,0)/Extra/com.apple.Boot.plist",
665"/Extra/com.apple.Boot.plist",
666"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
667"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
668"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
669"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
670};
671
672int i, fd, count, ret=-1;
673
674for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
675{
676if ((fd = open(dirspec[i], 0)) >= 0)
677{
678// read file
679count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
680close(fd);
681
682// build xml dictionary
683ParseXMLFile(config->plist, &config->dictionary);
684sysConfigValid=1;
685ret=0;
686break;
687}
688}
689return ret;
690}
691
692/* loadHelperConfig
693 *
694 * Returns 0 - successful.
695 * -1 - unsuccesful.
696 */
697int loadHelperConfig(config_file_t *config)
698{
699char *dirspec[] = {
700"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
701"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
702"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
703};
704
705int i, fd, count, ret=-1;
706
707for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
708{
709if ((fd = open(dirspec[i], 0)) >= 0)
710{
711// read file
712count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
713close(fd);
714
715// build xml dictionary
716ParseXMLFile(config->plist, &config->dictionary);
717sysConfigValid=1;
718ret=0;
719break;
720}
721}
722return ret;
723}
724
725char * newString(const char * oldString)
726{
727 if ( oldString )
728 return strcpy(MALLOC(strlen(oldString)+1), oldString);
729 else
730 return NULL;
731}
732
733/*
734 * Extracts the next argument from the command line, double quotes are allowed here.
735 */
736char * getNextArg(char ** argPtr, char * val)
737{
738 char * ptr = *argPtr;
739 const char * strStart;
740 int len = 0;
741 BOOL isQuoted = FALSE;
742
743 *val = '\0';
744
745 // Scan for the next non-whitespace character.
746 while ( *ptr && (*ptr == ' ' || *ptr == '=') )
747 {
748 ptr++;
749 }
750
751 strStart = ptr;
752
753 // Skip the leading double quote character.
754 if (*ptr == '\"')
755 {
756 isQuoted = TRUE;
757 ptr++;
758 strStart++;
759 }
760
761 // Scan for the argument terminator character.
762 // This can be either a NULL character - in case we reach the end of the string,
763 // a double quote in case of quoted argument,
764 // or a whitespace character (' ' or '=') for non-quoted argument.
765 while (*ptr && !( (isQuoted && (*ptr == '\"')) ||
766 (!isQuoted && (*ptr == ' ' || *ptr == '=')) )
767 )
768 {
769 ptr++;
770 }
771
772 len = ptr - strStart;
773
774 // Skip the closing double quote character and adjust
775 // the starting pointer for the next getNextArg call.
776 if (*ptr && isQuoted && *ptr == '\"')
777 ptr++;
778
779 // Copy the extracted argument to val.
780 strncat(val, strStart, len);
781
782 // Set command line pointer.
783 *argPtr = ptr;
784
785 return ptr;
786}
787

Archive Download this file

Revision: 4