Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/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 "libsaio.h"
30//#include "bootstruct.h"
31#include "boot.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 == '\\') {
49 switch(c = *key++) {
50 case 'n':
51c = '\n';
52break;
53 case 'r':
54c = '\r';
55break;
56 case 't':
57c = '\t';
58break;
59 default:
60break;
61 }
62} else if (c == '\"') {
63 /* Premature end of key */
64 return 1;
65}
66if (c != *str++) {
67 return 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(
228char *table,
229char *key,
230config_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++) {
240 if ((*p = *val) == '\\') {
241switch (*++val) {
242case 'r':
243 *p = '\r';
244 break;
245case 'n':
246 *p = '\n';
247 break;
248case 't':
249 *p = '\t';
250 break;
251default:
252 *p = *val;
253 break;
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 != '\"')
294 line++;
295*len = line++ - *begin;
296 } else {
297*begin = line;
298while (*line && !isspace(*line) && *line != '=')
299 line++;
300*len = line - *begin;
301 }
302 return line;
303}
304// bootArgs->CommandLine, key, val, size
305bool getValueForBootKey(const char *line, const char *match, const char **matchval, int *len)
306{
307const char *key, *value;
308int key_len, value_len;
309bool retval = false;
310
311while (*line)
312{
313/* look for keyword or argument */
314while (isspace(*line)) line++;
315
316/* now look for '=' or whitespace */
317line = getToken(line, &key, &key_len);
318
319/* line now points to '=' or space */
320if (*line && !isspace(*line)) {
321line = getToken(++line, &value, &value_len);
322}
323else
324{
325value = line;
326value_len = 0;
327}
328
329if ((strlen(match) == key_len) && strncmp(match, key, key_len) == 0) {
330*matchval = value;
331*len = value_len;
332
333retval = true;
334/* Continue to look for this key; last one wins. */
335}
336}
337return retval;
338}
339
340/* Return NULL if no option has been successfully retrieved, or the string otherwise */
341const char * getStringForKey(const char * key, config_file_t *config)
342{
343static const char* value = 0;
344int len = 0;
345
346if (!getValueForKey(key, &value, &len, config))
347value = 0;
348
349return value;
350}
351
352
353/* Returns TRUE if a value was found, FALSE otherwise.
354 * The boolean value of the key is stored in 'val'.
355 */
356
357bool getBoolForKey( const char *key, bool *result_val, config_file_t *config )
358{
359 const char *key_val;
360 int size;
361
362 if (getValueForKey(key, &key_val, &size, config)) {
363 if ( (size >= 1) && (key_val[0] == 'Y' || key_val[0] == 'y') ) {
364 *result_val = true;
365 } else {
366 *result_val = false;
367 }
368 return true;
369 }
370 return false;
371}
372
373bool getIntForKey( const char *key, int *value, config_file_t *config )
374{
375 const char *val;
376 int size, sum;
377 bool negative = false;
378
379 if (getValueForKey(key, &val, &size, config))
380{
381if ( size )
382{
383if (*val == '-')
384{
385negative = true;
386val++;
387size--;
388}
389
390for (sum = 0; size > 0; size--)
391{
392if (*val < '0' || *val > '9')
393return false;
394
395sum = (sum * 10) + (*val++ - '0');
396}
397
398if (negative)
399sum = -sum;
400
401*value = sum;
402return true;
403}
404}
405 return false;
406}
407
408/*
409 *
410 */
411
412bool getDimensionForKey( const char *key, unsigned int *value, config_file_t *config, unsigned int dimension_max, unsigned int object_size )
413{
414const char *val;
415
416 int size = 0;
417int sum = 0;
418
419bool negative = false;
420bool percentage = false;
421
422 if (getValueForKey(key, &val, &size, config))
423{
424if ( size )
425{
426if (*val == '-')
427{
428negative = true;
429val++;
430size--;
431}
432
433if (val[size-1] == '%')
434{
435percentage = true;
436size--;
437}
438
439// convert string to integer
440for (sum = 0; size > 0; size--)
441{
442if (*val < '0' || *val > '9')
443return false;
444
445sum = (sum * 10) + (*val++ - '0');
446}
447
448if (percentage)
449sum = ( dimension_max * sum ) / 100;
450
451// calculate offset from opposite origin
452if (negative)
453sum = ( ( dimension_max - object_size ) - sum );
454
455} else {
456
457// null value calculate center
458sum = ( dimension_max - object_size ) / 2;
459
460}
461
462*value = (uint16_t) sum;
463return true;
464}
465
466// key not found
467 return false;
468}
469
470/*
471 *get color value from plist format #RRGGBB
472 */
473
474bool getColorForKey( const char *key, unsigned int *value, config_file_t *config )
475{
476 const char *val;
477 int size;
478
479 if (getValueForKey(key, &val, &size, config))
480{
481if (*val == '#')
482{
483 val++;
484*value = strtol(val, NULL, 16);
485return true;
486 }
487 }
488 return false;
489}
490
491bool getValueForKey( const char *key, const char **val, int *size, config_file_t *config )
492{
493 const char *overrideVal;
494 int overrideSize;
495 bool override, ret;
496//Azi: bootargs
497 if (getValueForBootKey(bootArgs->CommandLine, key, val, size))
498 return true;
499
500 ret = getValueForConfigTableKey(config, key, val, size);
501
502 // Try to find alternate keys in bootInfo->overrideConfig
503 // and prefer its values with the exceptions for
504 // "Kernel"="mach_kernel" and "Kernel Flags"="".
505
506 if (config->canOverride)
507 {
508 if (getValueForConfigTableKey(&bootInfo->overrideConfig, key, &overrideVal, &overrideSize))
509 {
510 override = true;
511
512 if (ret && (strcmp(key, kKernelNameKey) == 0) && (strcmp(overrideVal, kDefaultKernelName) == 0))
513 override = false;
514
515 if (ret && (strcmp(key, kKernelFlagsKey) == 0) && (overrideSize == 0))
516 override = false;
517
518 if (override)
519 {
520 *val = overrideVal;
521 *size = overrideSize;
522 return true;
523 }
524 }
525 }
526
527 return ret;
528}
529
530
531#if UNUSED
532void
533printSystemConfig(char *p1)
534{
535 char *p2 = p1, tmp;
536
537 while (*p1 != '\0') {
538while (*p2 != '\0' && *p2 != '\n') p2++;
539tmp = *p2;
540*p2 = '\0';
541printf("%s\n", p1);
542*p2 = tmp;
543if (tmp == '\0') break;
544p1 = ++p2;
545 }
546}
547#endif
548
549//==========================================================================
550// ParseXMLFile
551// Modifies the input buffer.
552// Expects to see one dictionary in the XML file.
553// Puts the first dictionary it finds in the
554// tag pointer and returns 0, or returns -1 if not found
555// (and does not modify dict pointer).
556// Prints an error message if there is a parsing error.
557//
558int ParseXMLFile( char * buffer, TagPtr * dict )
559{
560 long length, pos;
561 TagPtr tag;
562 pos = 0;
563 char *configBuffer;
564
565 configBuffer = malloc(strlen(buffer)+1);
566 strcpy(configBuffer, buffer);
567
568 while (1)
569 {
570 length = XMLParseNextTag(configBuffer + pos, &tag);
571 if (length == -1) break;
572
573 pos += length;
574
575 if (tag == 0) continue;
576 if (tag->type == kTagTypeDict) break;
577
578 XMLFreeTag(tag);
579 }
580 free(configBuffer);
581 if (length < 0) {
582 error ("Error parsing plist file\n");
583 return -1;
584 }
585 *dict = tag;
586 return 0;
587}
588
589/* loadConfigFile
590 *
591 * Returns 0 - successful.
592 * -1 - unsuccesful.
593 */
594int loadConfigFile(const char *configFile, config_file_t *config)
595{
596int fd, count;
597//Azi: check Mek ?? it makes sense, or doesn't ??? :P
598if ((fd = open_bvdev("bt(0,0)", configFile, 0)) < 0) {
599return -1;
600}
601// read file
602count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
603close(fd);
604
605// build xml dictionary
606ParseXMLFile(config->plist, &config->dictionary);
607return 0;
608}
609
610
611/* loadSystemConfig
612 *
613 * Returns 0 - successful.
614 * -1 - unsuccesful.
615 */
616int loadSystemConfig(config_file_t *config)
617{
618char *dirspec[] = {
619"/Extra/com.apple.Boot.plist", //Azi: Boot Volume is set as Root at this point so,
620// pointing to Extra, /Extra or bt(0,0)/Extra, is exactly the same. Check setBootGlobals()
621//"bt(0,0)/Extra/com.apple.Boot.plist",
622"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
623"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
624"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
625"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
626};
627
628int i, fd, count, ret=-1;
629
630for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
631{
632if ((fd = open(dirspec[i], 0)) >= 0)
633{
634// read file
635count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
636close(fd);
637
638// build xml dictionary
639ParseXMLFile(config->plist, &config->dictionary);
640sysConfigValid = true;
641ret=0;
642
643// enable canOverride flag
644config->canOverride = true;
645
646// disable canOverride. Remove?
647getBoolForKey(kCanOverrideKey, &config->canOverride, &bootInfo->bootConfig);
648
649break;
650}
651}
652return ret;
653}
654
655/* loadOverrideConfig
656 *
657 * Returns 0 - successful.
658 * -1 - unsuccesful.
659bool getValueForKey( const char *key, const char **val, int *size, config_file_t *config ) */
660int loadOverrideConfig(config_file_t *config)
661{
662char dirSpecBplist[128] = "";
663const char*override_pathname = NULL;
664const char*filename = "com.apple.Boot.plist";
665int count, ret, fd, len = 0;
666
667// Take in account user overriding the override :P
668// Damn thing doesn't work anymore ?????? :-/
669if (getValueForKey(kAltConfigKey, &override_pathname, &len, config)) // config ??
670{
671// Specify a path to a file, e.g. config=/Extra/test.plist
672strcpy(dirSpecBplist, override_pathname);
673fd = open(dirSpecBplist, 0);
674if (fd >= 0) goto success_fd;
675}
676
677// Check rd's root for override config.
678sprintf(dirSpecBplist, "rd(0,0)/%s", filename);
679fd = open(dirSpecBplist, 0);
680if (fd >= 0) goto success_fd;
681
682// Check specific OS folders.
683sprintf(dirSpecBplist, "bt(0,0)/Extra/%s/%s", &gMacOSVersion, filename);
684fd = open(dirSpecBplist, 0);
685if (fd >= 0) goto success_fd;
686
687//can be useful with ramdisks...
688sprintf(dirSpecBplist, "bt(0,0)/Extra/%s", filename);
689fd = open(dirSpecBplist, 0);
690if (fd >= 0) goto success_fd;
691
692//Azi: i really don't like these two!
693// "/Extra/com.apple.Boot.plist"
694// "/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
695
696//Azi: RESTORE THESE PATHS!
697// "/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
698// "/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
699// "/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
700
701success_fd:
702
703if (fd >= 0)
704{
705// read file
706count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
707close(fd);
708
709// build xml dictionary
710ParseXMLFile(config->plist, &config->dictionary);
711sysConfigValid = true;
712ret = 0;
713}
714else
715{
716verbose("No override config provided!\n");
717ret = -1;
718}
719return ret;
720}
721
722/* loadHelperConfig
723 *
724 * Returns 0 - successful.
725 * -1 - unsuccesful.
726 */
727int loadHelperConfig(config_file_t *config)
728{
729//Azi: UPDATE WITH MEK'S CODE!
730char *dirspec[] = {
731"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
732"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
733"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
734};
735
736int i, fd, count, ret=-1;
737
738for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
739{
740if ((fd = open(dirspec[i], 0)) >= 0)
741{
742// read file
743count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
744close(fd);
745
746// build xml dictionary
747ParseXMLFile(config->plist, &config->dictionary);
748sysConfigValid = true;
749ret=0;
750break;
751}
752}
753return ret;
754}
755
756char * newString(const char * oldString)
757{
758 if ( oldString )
759 return strcpy(malloc(strlen(oldString)+1), oldString);
760 else
761 return NULL;
762}
763
764/*
765 * Extracts the next argument from the command line, double quotes are allowed here.
766 */
767char * getNextArg(char ** argPtr, char * val)
768{
769 char * ptr = *argPtr;
770 const char * strStart;
771 int len = 0;
772 bool isQuoted = false;
773
774 *val = '\0';
775
776 // Scan for the next non-whitespace character.
777 while ( *ptr && (*ptr == ' ' || *ptr == '=') )
778 {
779 ptr++;
780 }
781
782 strStart = ptr;
783
784 // Skip the leading double quote character.
785 if (*ptr == '\"')
786 {
787 isQuoted = true;
788 ptr++;
789 strStart++;
790 }
791
792 // Scan for the argument terminator character.
793 // This can be either a NULL character - in case we reach the end of the string,
794 // a double quote in case of quoted argument,
795 // or a whitespace character (' ' or '=') for non-quoted argument.
796 while (*ptr && !( (isQuoted && (*ptr == '\"')) ||
797 (!isQuoted && (*ptr == ' ' || *ptr == '=')) )
798 )
799 {
800 ptr++;
801 }
802
803 len = ptr - strStart;
804
805 // Skip the closing double quote character and adjust
806 // the starting pointer for the next getNextArg call.
807 if (*ptr && isQuoted && *ptr == '\"')
808 ptr++;
809
810 // Copy the extracted argument to val.
811 strncat(val, strStart, len);
812
813 // Set command line pointer.
814 *argPtr = ptr;
815
816 return ptr;
817}
818

Archive Download this file

Revision: 840