Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 429