Chameleon

Chameleon Svn Source Tree

Root/tags/2.0/i386/libsaio/stringTable.c

Source at commit 1808 created 12 years 3 months ago.
By blackosx, Revise layout of package installer 'Welcome' file so it looks cleaner. Change the copyright notice to begin from 2009 as seen in the Chameleon 2.0 r431 installer. Should this date be set earlier?
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 *
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
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)) {
319 line = getToken(++line, &value, &value_len);
320} else {
321 value = line;
322 value_len = 0;
323}
324if ((strlen(match) == key_len)
325 && strncmp(match, key, key_len) == 0) {
326// create a new string
327char* newstr = malloc(value_len + 1);
328strncpy(newstr, value, value_len);
329newstr[value_len] = 0;
330
331 *matchval = newstr;
332 *len = value_len;
333 retval = true;
334 /* Continue to look for this key; last one wins. */
335}
336 }
337
338
339 return retval;
340}
341
342/* Return NULL if no option has been successfully retrieved, or the string otherwise */
343const char * getStringForKey(const char * key, config_file_t *config)
344{
345 static const char* value =0;
346 int len=0;
347 if(!getValueForKey(key, &value, &len, config)) value = 0;
348 return value;
349}
350
351
352/* Returns TRUE if a value was found, FALSE otherwise.
353 * The boolean value of the key is stored in 'val'.
354 */
355
356bool getBoolForKey( const char *key, bool *result_val, config_file_t *config )
357{
358 const char *key_val;
359 int size;
360
361 if (getValueForKey(key, &key_val, &size, config)) {
362 if ( (size >= 1) && (key_val[0] == 'Y' || key_val[0] == 'y') ) {
363 *result_val = true;
364 } else {
365 *result_val = false;
366 }
367 return true;
368 }
369 return false;
370}
371
372bool getIntForKey( const char *key, int *value, config_file_t *config )
373{
374 const char *val;
375 int size, sum;
376 bool negative = false;
377
378 if (getValueForKey(key, &val, &size, config))
379{
380if ( size )
381{
382if (*val == '-')
383{
384negative = true;
385val++;
386size--;
387}
388
389for (sum = 0; size > 0; size--)
390{
391if (*val < '0' || *val > '9')
392return false;
393
394sum = (sum * 10) + (*val++ - '0');
395}
396
397if (negative)
398sum = -sum;
399
400*value = sum;
401return true;
402}
403}
404 return false;
405}
406
407/*
408 *
409 */
410
411bool getDimensionForKey( const char *key, unsigned int *value, config_file_t *config, unsigned int dimension_max, unsigned int object_size )
412{
413const char *val;
414
415 int size = 0;
416int sum = 0;
417
418bool negative = false;
419bool percentage = false;
420
421 if (getValueForKey(key, &val, &size, config))
422{
423if ( size )
424{
425if (*val == '-')
426{
427negative = true;
428val++;
429size--;
430}
431
432if (val[size-1] == '%')
433{
434percentage = true;
435size--;
436}
437
438// convert string to integer
439for (sum = 0; size > 0; size--)
440{
441if (*val < '0' || *val > '9')
442return false;
443
444sum = (sum * 10) + (*val++ - '0');
445}
446
447if (percentage)
448sum = ( dimension_max * sum ) / 100;
449
450// calculate offset from opposite origin
451if (negative)
452sum = ( ( dimension_max - object_size ) - sum );
453
454} else {
455
456// null value calculate center
457sum = ( dimension_max - object_size ) / 2;
458
459}
460
461*value = (uint16_t) sum;
462return true;
463}
464
465// key not found
466 return false;
467}
468
469/*
470 *get color value from plist format #RRGGBB
471 */
472
473bool getColorForKey( const char *key, unsigned int *value, config_file_t *config )
474{
475 const char *val;
476 int size;
477
478 if (getValueForKey(key, &val, &size, config))
479{
480if (*val == '#')
481{
482 val++;
483*value = strtol(val, NULL, 16);
484return true;
485 }
486 }
487 return false;
488}
489
490bool getValueForKey( const char *key, const char **val, int *size, config_file_t *config )
491{
492 const char *overrideVal;
493 int overrideSize;
494 bool override, ret;
495
496 if (getValueForBootKey(bootArgs->CommandLine, key, val, size))
497 return true;
498
499 ret = getValueForConfigTableKey(config, key, val, size);
500
501 // Try to find alternate keys in bootInfo->overrideConfig
502 // and prefer its values with the exceptions for
503 // "Kernel"="mach_kernel" and "Kernel Flags"="".
504
505 if (config->canOverride)
506 {
507 if (getValueForConfigTableKey(&bootInfo->chameleonConfig, key, &overrideVal, &overrideSize))
508 {
509 override = true;
510
511 // NOTE: Values are defined by apple as being in com.apple.Boot.plist
512 // kHelperRootUUIDKey, kKernelArchKey, kMKextCacheKey, kKernelCacheKey, kKernelNameKey, kKernelFlagsKey
513 if (ret && (strcmp(key, kKernelNameKey) == 0) && (overrideSize == 0))
514 override = false;
515
516 if (ret && (strcmp(key, kKernelFlagsKey) == 0) && (overrideSize == 0))
517 override = false;
518
519 if (override)
520 {
521 *val = overrideVal;
522 *size = overrideSize;
523 return true;
524 }
525 }
526 }
527
528 return ret;
529}
530
531
532#if UNUSED
533void
534printSystemConfig(char *p1)
535{
536 char *p2 = p1, tmp;
537
538 while (*p1 != '\0') {
539while (*p2 != '\0' && *p2 != '\n') p2++;
540tmp = *p2;
541*p2 = '\0';
542printf("%s\n", p1);
543*p2 = tmp;
544if (tmp == '\0') break;
545p1 = ++p2;
546 }
547}
548#endif
549
550//==========================================================================
551// ParseXMLFile
552// Modifies the input buffer.
553// Expects to see one dictionary in the XML file.
554// Puts the first dictionary it finds in the
555// tag pointer and returns 0, or returns -1 if not found
556// (and does not modify dict pointer).
557// Prints an error message if there is a parsing error.
558//
559int ParseXMLFile( char * buffer, TagPtr * dict )
560{
561 long length, pos;
562 TagPtr tag;
563 pos = 0;
564 char *configBuffer;
565
566 configBuffer = malloc(strlen(buffer)+1);
567 strcpy(configBuffer, buffer);
568
569 while (1)
570 {
571 length = XMLParseNextTag(configBuffer + pos, &tag);
572 if (length == -1) break;
573
574 pos += length;
575
576 if (tag == 0) continue;
577 if (tag->type == kTagTypeDict) break;
578
579 XMLFreeTag(tag);
580 }
581 free(configBuffer);
582 if (length < 0) {
583 error ("Error parsing plist file\n");
584 return -1;
585 }
586 *dict = tag;
587 return 0;
588}
589
590/* loadConfigFile
591 *
592 * Returns 0 - successful.
593 * -1 - unsuccesful.
594 */
595int loadConfigFile (const char *configFile, config_file_t *config)
596{
597int fd, count;
598
599if ((fd = open_bvdev("bt(0,0)", configFile, 0)) < 0) {
600return -1;
601}
602// read file
603count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
604close(fd);
605
606// build xml dictionary
607ParseXMLFile(config->plist, &config->dictionary);
608return 0;
609}
610
611
612/* loadSystemConfig
613 *
614 * Returns 0 - successful.
615 * -1 - unsuccesful.
616 */
617int loadSystemConfig(config_file_t *config)
618{
619char *dirspec[] = {
620"/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
621};
622
623int i, fd, count, ret=-1;
624
625for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
626{
627if ((fd = open(dirspec[i], 0)) >= 0)
628{
629// read file
630count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
631close(fd);
632
633// build xml dictionary
634ParseXMLFile(config->plist, &config->dictionary);
635sysConfigValid = true;
636ret=0;
637
638// enable canOverride flag
639config->canOverride = true;
640
641break;
642}
643}
644if(ret == -1) ret = loadHelperConfig(config);
645return ret;
646}
647
648/* loadChameleonConfig
649 *
650 * Returns 0 - successful.
651 * -1 - unsuccesful.
652 */
653int loadChameleonConfig(config_file_t *config)
654{
655char *dirspec[] = {
656"rd(0,0)/Extra/org.chameleon.Boot.plist",
657"/Extra/org.chameleon.Boot.plist",
658"bt(0,0)/Extra/org.chameleon.Boot.plist",
659
660"rd(0,0)/Extra/com.apple.Boot.plist", /* DEPRECIATED */
661"/Extra/com.apple.Boot.plist", /* DEPRECIATED */
662"bt(0,0)/Extra/com.apple.Boot.plist", /* DEPRECIATED */
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 // Check for depreciated file names and annoy the user about it.
672 if(strstr(dirspec[i], "com.apple.Boot.plist"))
673 {
674 printf("%s is depreciated.\n", dirspec[i]);
675 dirspec[i][strlen(dirspec[i]) - strlen("com.apple.Boot.plist")] = 0;
676 printf("Please use the file %sorg.chameleon.Boot.plist instead.\n", dirspec[i]);
677 pause();
678 }
679// read file
680count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
681close(fd);
682
683// build xml dictionary
684ParseXMLFile(config->plist, &config->dictionary);
685sysConfigValid = true;
686ret=0;
687break;
688}
689}
690return ret;
691}
692
693/* loadHelperConfig
694 *
695 * Returns 0 - successful.
696 * -1 - unsuccesful.
697 */
698int loadHelperConfig(config_file_t *config)
699{
700char *dirspec[] = {
701"/com.apple.boot.P/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
702"/com.apple.boot.R/Library/Preferences/SystemConfiguration/com.apple.Boot.plist",
703"/com.apple.boot.S/Library/Preferences/SystemConfiguration/com.apple.Boot.plist"
704};
705
706int i, fd, count, ret=-1;
707
708for(i = 0; i< sizeof(dirspec)/sizeof(dirspec[0]); i++)
709{
710if ((fd = open(dirspec[i], 0)) >= 0)
711{
712// read file
713count = read(fd, config->plist, IO_CONFIG_DATA_SIZE);
714close(fd);
715
716// build xml dictionary
717ParseXMLFile(config->plist, &config->dictionary);
718sysConfigValid = true;
719ret=0;
720break;
721}
722}
723return ret;
724}
725
726char * newString(const char * oldString)
727{
728 if ( oldString )
729 return strcpy(malloc(strlen(oldString)+1), oldString);
730 else
731 return NULL;
732}
733
734/*
735 * Extracts the next argument from the command line, double quotes are allowed here.
736 */
737char * getNextArg(char ** argPtr, char * val)
738{
739 char * ptr = *argPtr;
740 const char * strStart;
741 int len = 0;
742 bool isQuoted = false;
743
744 *val = '\0';
745
746 // Scan for the next non-whitespace character.
747 while ( *ptr && (*ptr == ' ' || *ptr == '=') )
748 {
749 ptr++;
750 }
751
752 strStart = ptr;
753
754 // Skip the leading double quote character.
755 if (*ptr == '\"')
756 {
757 isQuoted = true;
758 ptr++;
759 strStart++;
760 }
761
762 // Scan for the argument terminator character.
763 // This can be either a NULL character - in case we reach the end of the string,
764 // a double quote in case of quoted argument,
765 // or a whitespace character (' ' or '=') for non-quoted argument.
766 while (*ptr && !( (isQuoted && (*ptr == '\"')) ||
767 (!isQuoted && (*ptr == ' ' || *ptr == '=')) )
768 )
769 {
770 ptr++;
771 }
772
773 len = ptr - strStart;
774
775 // Skip the closing double quote character and adjust
776 // the starting pointer for the next getNextArg call.
777 if (*ptr && isQuoted && *ptr == '\"')
778 ptr++;
779
780 // Copy the extracted argument to val.
781 strncat(val, strStart, len);
782
783 // Set command line pointer.
784 *argPtr = ptr;
785
786 return ptr;
787}
788

Archive Download this file

Revision: 1808