Chameleon

Chameleon Svn Source Tree

Root/branches/ErmaC/Enoch_Modules/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 "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 *newStringFromList(char **list, int *size)
139{
140char *begin = *list, *end;
141char *newstr;
142int newsize = *size;
143int bufsize;
144
145while (*begin && newsize && isspace(*begin))
146{
147begin++;
148newsize--;
149}
150end = begin;
151while (*end && newsize && !isspace(*end))
152{
153end++;
154newsize--;
155}
156if (begin == end)
157{
158return 0;
159}
160bufsize = end - begin + 1;
161newstr = malloc(bufsize);
162strlcpy(newstr, begin, bufsize);
163*list = end;
164*size = newsize;
165return 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{
199// Look up key in XML dictionary
200TagPtr value;
201value = XMLGetProperty(config->dictionary, key);
202if (value != 0)
203{
204if (value->type != kTagTypeString)
205{
206error("Non-string tag '%s' found in config file\n", key);
207return false;
208}
209*val = value->string;
210*size = strlen(value->string);
211return true;
212}
213}
214else
215{
216
217// Legacy plist-style table
218
219}
220
221return false;
222}
223
224#if UNUSED
225
226/*
227 * Returns a new malloc'ed string if one is found
228 * in the string table matching 'key'. Also translates
229 * \n escapes in the string.
230 */
231char *newStringForStringTableKey(char *table, char *key, config_file_t *config)
232{
233const char *val;
234char *newstr, *p;
235int size;
236
237if (getValueForConfigTableKey(config, key, &val, &size))
238{
239newstr = (char *)malloc(size+1);
240for (p = newstr; size; size--, p++, val++)
241{
242if ((*p = *val) == '\\')
243{
244switch (*++val)
245{
246case 'r':
247*p = '\r';
248break;
249case 'n':
250*p = '\n';
251break;
252case 't':
253*p = '\t';
254break;
255default:
256*p = *val;
257break;
258}
259size--;
260}
261}
262*p = '\0';
263return newstr;
264}
265else
266{
267return 0;
268}
269}
270
271#endif
272
273char *
274newStringForKey(char *key, config_file_t *config)
275{
276const char *val;
277char *newstr;
278int size;
279
280if (getValueForKey(key, &val, &size, config) && size)
281{
282newstr = (char *)malloc(size + 1);
283strlcpy(newstr, val, size + 1);
284return newstr;
285}
286else
287{
288return 0;
289}
290}
291
292/* parse a command line
293 * in the form: [<argument> ...] [<option>=<value> ...]
294 * both <option> and <value> must be either composed of
295 * non-whitespace characters, or enclosed in quotes.
296 */
297
298static const char *getToken(const char *line, const char **begin, int *len)
299{
300 if (*line == '\"') {
301*begin = ++line;
302while (*line && *line != '\"')
303 line++;
304*len = line++ - *begin;
305 } else {
306*begin = line;
307while (*line && !isspace(*line) && *line != '=')
308 line++;
309*len = line - *begin;
310 }
311 return line;
312}
313
314bool getValueForBootKey(const char *line, const char *match, const char **matchval, int *len)
315{
316 const char *key, *value;
317 int key_len, value_len;
318 bool retval = false;
319
320 while (*line) {
321/* look for keyword or argument */
322while (isspace(*line)) line++;
323
324/* now look for '=' or whitespace */
325line = getToken(line, &key, &key_len);
326/* line now points to '=' or space */
327if (*line && !isspace(*line)) {
328 line = getToken(++line, &value, &value_len);
329} else {
330 value = line;
331 value_len = 0;
332}
333if ((strlen(match) == key_len)
334 && strncmp(match, key, key_len) == 0) {
335// create a new string
336char* newstr = malloc(value_len + 1);
337strncpy(newstr, value, value_len);
338newstr[value_len] = 0;
339
340 *matchval = newstr;
341 *len = value_len;
342 retval = true;
343 /* Continue to look for this key; last one wins. */
344}
345 }
346
347
348 return retval;
349}
350
351/* Return NULL if no option has been successfully retrieved, or the string otherwise */
352const char * getStringForKey(const char * key, config_file_t *config)
353{
354 static const char* value =0;
355 int len=0;
356 if(!getValueForKey(key, &value, &len, config)) value = 0;
357 return value;
358}
359
360
361/* Returns TRUE if a value was found, FALSE otherwise.
362 * The boolean value of the key is stored in 'val'.
363 */
364
365bool getBoolForKey( const char *key, bool *result_val, config_file_t *config )
366{
367 const char *key_val;
368 int size;
369
370 if (getValueForKey(key, &key_val, &size, config)) {
371 if ( (size >= 1) && (key_val[0] == 'Y' || key_val[0] == 'y') ) {
372 *result_val = true;
373 } else {
374 *result_val = false;
375 }
376 return true;
377 }
378 return false;
379}
380
381bool getIntForKey( const char *key, int *value, config_file_t *config )
382{
383 const char *val;
384 int size, sum;
385 bool negative = false;
386
387 if (getValueForKey(key, &val, &size, config))
388{
389if ( size )
390{
391if (*val == '-')
392{
393negative = true;
394val++;
395size--;
396}
397
398for (sum = 0; size > 0; size--)
399{
400if (*val < '0' || *val > '9')
401return false;
402
403sum = (sum * 10) + (*val++ - '0');
404}
405
406if (negative)
407sum = -sum;
408
409*value = sum;
410return true;
411}
412}
413 return false;
414}
415
416/*
417 *
418 */
419
420bool getDimensionForKey( const char *key, unsigned int *value, config_file_t *config, unsigned int dimension_max, unsigned int object_size )
421{
422const char *val;
423
424 int size = 0;
425int sum = 0;
426
427bool negative = false;
428bool percentage = false;
429
430 if (getValueForKey(key, &val, &size, config))
431{
432if ( size )
433{
434if (*val == '-')
435{
436negative = true;
437val++;
438size--;
439}
440
441if (val[size-1] == '%')
442{
443percentage = true;
444size--;
445}
446
447// convert string to integer
448for (sum = 0; size > 0; size--)
449{
450if (*val < '0' || *val > '9')
451return false;
452
453sum = (sum * 10) + (*val++ - '0');
454}
455
456if (percentage)
457sum = ( dimension_max * sum ) / 100;
458
459// calculate offset from opposite origin
460if (negative)
461sum = ( ( dimension_max - object_size ) - sum );
462
463} else {
464
465// null value calculate center
466sum = ( dimension_max - object_size ) / 2;
467
468}
469
470*value = (uint16_t) sum;
471return true;
472}
473
474// key not found
475 return false;
476}
477
478/*
479 *get color value from plist format #RRGGBB
480 */
481
482bool getColorForKey( const char *key, unsigned int *value, config_file_t *config )
483{
484 const char *val;
485 int size;
486
487 if (getValueForKey(key, &val, &size, config))
488{
489if (*val == '#')
490{
491 val++;
492*value = strtol(val, NULL, 16);
493return true;
494 }
495 }
496 return false;
497}
498
499bool getValueForKey( const char *key, const char **val, int *size, config_file_t *config )
500{
501 const char *overrideVal;
502 int overrideSize;
503 bool override, ret;
504
505 if (getValueForBootKey(bootArgs->CommandLine, key, val, size))
506 return true;
507
508 ret = getValueForConfigTableKey(config, key, val, size);
509
510 // Try to find alternate keys in bootInfo->chameleonConfig (if config can be overriden)
511 // and prefer its values with the exceptions for
512 // "Kernel"="mach_kernel" and "Kernel Flags"="".
513
514 if (config->canOverride)
515 {
516 if (getValueForConfigTableKey(&bootInfo->chameleonConfig, key, &overrideVal, &overrideSize))
517 {
518 override = true;
519
520 // NOTE: Values are defined by apple as being in com.apple.Boot.plist
521 // kHelperRootUUIDKey, kKernelArchKey, kMKextCacheKey, kKernelCacheKey, kKernelNameKey, kKernelFlagsKey
522 if (ret && (strcmp(key, kKernelNameKey) == 0) && (overrideSize == 0))
523 override = false;
524
525 if (ret && (strcmp(key, kKernelFlagsKey) == 0) && (overrideSize == 0))
526 override = false;
527
528 if (override)
529 {
530 *val = overrideVal;
531 *size = overrideSize;
532 return true;
533 }
534 }
535 }
536
537 return ret;
538}
539
540
541#if UNUSED
542void
543printSystemConfig(char *p1)
544{
545 char *p2 = p1, tmp;
546
547 while (*p1 != '\0') {
548while (*p2 != '\0' && *p2 != '\n') p2++;
549tmp = *p2;
550*p2 = '\0';
551printf("%s\n", p1);
552*p2 = tmp;
553if (tmp == '\0') break;
554p1 = ++p2;
555 }
556}
557#endif
558
559//==========================================================================
560// ParseXMLFile
561// Modifies the input buffer.
562// Expects to see one dictionary in the XML file.
563// Puts the first dictionary it finds in the
564// tag pointer and returns 0, or returns -1 if not found
565// (and does not modify dict pointer).
566// Prints an error message if there is a parsing error.
567//
568int ParseXMLFile( char * buffer, TagPtr * dict )
569{
570 long length, pos;
571 TagPtr tag;
572 pos = 0;
573 char *configBuffer;
574
575 configBuffer = malloc(strlen(buffer)+1);
576 strcpy(configBuffer, buffer);
577
578 while (1)
579 {
580 length = XMLParseNextTag(configBuffer + pos, &tag);
581 if (length == -1) break;
582
583 pos += length;
584
585 if (tag == 0) continue;
586 if (tag->type == kTagTypeDict) break;
587
588 XMLFreeTag(tag);
589 }
590 free(configBuffer);
591 if (length < 0) {
592 error ("Error parsing plist file\n");
593 return -1;
594 }
595 *dict = tag;
596 return 0;
597}
598
599/* loadConfigFile
600 *
601 * Returns 0 - successful.
602 * -1 - unsuccesful.
603 */
604int loadConfigFile (const char *configFile, config_file_t *config)
605{
606int fd, count;
607
608if ((fd = open_bvdev("bt(0,0)", configFile, 0)) < 0) {
609return -1;
610}
611// read file
612count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
613close(fd);
614
615// build xml dictionary
616ParseXMLFile(config->plist, &config->dictionary);
617return 0;
618}
619
620
621/* loadSystemConfig
622 *
623 * Returns 0 - successful.
624 * -1 - unsuccesful.
625 */
626int loadSystemConfig(config_file_t *config)
627{
628char *dirspec[] = {
629"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
630"/OS X Install Data/com.apple.Boot.plist",
631};
632
633int i, fd, count, ret=-1;
634
635for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
636{
637if ((fd = open(dirspec[i], 0)) >= 0)
638{
639// read file
640count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
641close(fd);
642
643// build xml dictionary
644ParseXMLFile(config->plist, &config->dictionary);
645sysConfigValid = true;
646ret=0;
647
648break;
649}
650}
651
652if(ret == -1) ret = loadHelperConfig(config);
653
654// Always enable canOverride flag (for SystemConfig)
655config->canOverride = true;
656
657return ret;
658}
659
660/* loadChameleonConfig
661 *
662 * Returns 0 - successful.
663 * -1 - unsuccesful.
664 */
665int loadChameleonConfig(config_file_t *config)
666{
667char *dirspec[] = {
668"rd(0,0)/Extra/org.chameleon.Boot.plist",
669"/Extra/org.chameleon.Boot.plist",
670"bt(0,0)/Extra/org.chameleon.Boot.plist",
671
672"rd(0,0)/Extra/com.apple.Boot.plist", /* DEPRECIATED */
673"/Extra/com.apple.Boot.plist", /* DEPRECIATED */
674"bt(0,0)/Extra/com.apple.Boot.plist", /* DEPRECIATED */
675};
676
677int i, fd, count, ret=-1;
678
679for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
680{
681if ((fd = open(dirspec[i], 0)) >= 0)
682{
683 // Check for depreciated file names and annoy the user about it.
684 if(strstr(dirspec[i], "com.apple.Boot.plist"))
685 {
686 printf("%s is depreciated.\n", dirspec[i]);
687 dirspec[i][strlen(dirspec[i]) - strlen("com.apple.Boot.plist")] = 0;
688 printf("Please use the file %sorg.chameleon.Boot.plist instead.\n", dirspec[i]);
689 pause();
690 }
691// read file
692count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
693close(fd);
694
695// build xml dictionary
696ParseXMLFile(config->plist, &config->dictionary);
697sysConfigValid = true;
698ret=0;
699break;
700}
701}
702return ret;
703}
704
705/* loadHelperConfig
706 *
707 * Returns 0 - successful.
708 * -1 - unsuccesful.
709 */
710int loadHelperConfig(config_file_t *config)
711{
712char *dirspec[] = {
713"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
714"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
715"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
716};
717
718int i, fd, count, ret=-1;
719
720for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
721{
722if ((fd = open(dirspec[i], 0)) >= 0)
723{
724// read file
725count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
726close(fd);
727
728// build xml dictionary
729ParseXMLFile(config->plist, &config->dictionary);
730sysConfigValid = true;
731ret=0;
732break;
733}
734}
735return ret;
736}
737
738char * newString(const char * oldString)
739{
740 if ( oldString )
741 return strcpy(malloc(strlen(oldString)+1), oldString);
742 else
743 return NULL;
744}
745
746/*
747 * Extracts the next argument from the command line, double quotes are allowed here.
748 */
749char * getNextArg(char ** argPtr, char * val)
750{
751 char * ptr = *argPtr;
752 const char * strStart;
753 int len = 0;
754 bool isQuoted = false;
755
756 *val = '\0';
757
758 // Scan for the next non-whitespace character.
759 while ( *ptr && (*ptr == ' ' || *ptr == '=') )
760 {
761 ptr++;
762 }
763
764 strStart = ptr;
765
766 // Skip the leading double quote character.
767 if (*ptr == '\"')
768 {
769 isQuoted = true;
770 ptr++;
771 strStart++;
772 }
773
774 // Scan for the argument terminator character.
775 // This can be either a NULL character - in case we reach the end of the string,
776 // a double quote in case of quoted argument,
777 // or a whitespace character (' ' or '=') for non-quoted argument.
778 while (*ptr && !( (isQuoted && (*ptr == '\"')) ||
779 (!isQuoted && (*ptr == ' ' || *ptr == '=')) )
780 )
781 {
782 ptr++;
783 }
784
785 len = ptr - strStart;
786
787 // Skip the closing double quote character and adjust
788 // the starting pointer for the next getNextArg call.
789 if (*ptr && isQuoted && *ptr == '\"')
790 ptr++;
791
792 // Copy the extracted argument to val.
793 strncat(val, strStart, len);
794
795 // Set command line pointer.
796 *argPtr = ptr;
797
798 return ptr;
799}
800

Archive Download this file

Revision: 2238