Chameleon

Chameleon Svn Source Tree

Root/branches/mozodojo/i386/libsaio/stringTable.c

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

Archive Download this file

Revision: 755