Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 125