]> git.saurik.com Git - apple/boot.git/blame - i386/libsaio/stringTable.c
boot-83.2.tar.gz
[apple/boot.git] / i386 / libsaio / stringTable.c
CommitLineData
14c7c974
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999 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 1.1 (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 "kernBootStruct.h"
31#include "stringConstants.h"
14c7c974
A
32#include "legacy/configTablePrivate.h"
33
34extern KERNBOOTSTRUCT *kernBootStruct;
35extern char *Language;
36extern char *LoadableFamilies;
37
38static void eatThru(char val, char **table_p);
39
40static inline int isspace(char c)
41{
42 return (c == ' ' || c == '\t');
43}
44
45/*
46 * Compare a string to a key with quoted characters
47 */
48static inline int
49keyncmp(char *str, char *key, int n)
50{
51 int c;
52 while (n--) {
53 c = *key++;
54 if (c == '\\') {
55 switch(c = *key++) {
56 case 'n':
57 c = '\n';
58 break;
59 case 'r':
60 c = '\r';
61 break;
62 case 't':
63 c = '\t';
64 break;
65 default:
66 break;
67 }
68 } else if (c == '\"') {
69 /* Premature end of key */
70 return 1;
71 }
72 if (c != *str++) {
73 return 1;
74 }
75 }
76 return 0;
77}
78
79static void eatThru(char val, char **table_p)
80{
81 register char *table = *table_p;
82 register BOOL found = NO;
83
84 while (*table && !found)
85 {
86 if (*table == '\\') table += 2;
87 else
88 {
89 if (*table == val) found = YES;
90 table++;
91 }
92 }
93 *table_p = table;
94}
95
96/* Remove key and its associated value from the table. */
97
98BOOL
99removeKeyFromTable(const char *key, char *table)
100{
101 register int len;
102 register char *tab;
103 char *buf;
104
105 len = strlen(key);
106 tab = (char *)table;
107 buf = (char *)malloc(len + 3);
108
109 sprintf(buf, "\"%s\"", key);
110 len = strlen(buf);
111
112 while(*tab) {
113 if(strncmp(buf, tab, len) == 0) {
114 char c;
115
116 while((c = *(tab + len)) != ';') {
117 if(c == 0) {
118 len = -1;
119 goto out;
120 }
121 len++;
122 }
123 len++;
124 if(*(tab + len) == '\n') len++;
125 goto out;
126 }
127 tab++;
128 }
129 len = -1;
130out:
131 free(buf);
132
133 if(len == -1) return NO;
134
135 while((*tab = *(tab + len))) {
136 tab++;
137 }
138
139 return YES;
140}
141
142char *
143newStringFromList(
144 char **list,
145 int *size
146)
147{
148 char *begin = *list, *end;
149 char *newstr;
150 int newsize = *size;
151
152 while (*begin && newsize && isspace(*begin)) {
153 begin++;
154 newsize--;
155 }
156 end = begin;
157 while (*end && newsize && !isspace(*end)) {
158 end++;
159 newsize--;
160 }
161 if (begin == end)
162 return 0;
163 newstr = malloc(end - begin + 1);
164 strncpy(newstr, begin, end - begin);
165 *list = end;
166 *size = newsize;
167 return newstr;
168}
169
170/*
171 * compress == compress escaped characters to one character
172 */
173int stringLength(char *table, int compress)
174{
175 int ret = 0;
176
177 while (*table)
178 {
179 if (*table == '\\')
180 {
181 table += 2;
182 ret += 1 + (compress ? 0 : 1);
183 }
184 else
185 {
186 if (*table == '\"') return ret;
187 ret++;
188 table++;
189 }
190 }
191 return ret;
192}
193
194// looks in table for strings of format << "key" = "value"; >>
195// or << "key"; >>
196BOOL getValueForStringTableKey(char *table, char *key, char **val, int *size)
197{
198 int keyLength;
199 char *tableKey;
200
201 do
202 {
203 eatThru('\"',&table);
204 tableKey = table;
205 keyLength = strlen(key);
206 if (keyLength &&
207 (stringLength(table,1) == keyLength) &&
208 (keyncmp(key, table, keyLength) == 0))
209 {
210 int c;
211
212 /* found the key; now look for either
213 * '=' or ';'
214 */
215 while (c = *table) {
216 ++table;
217 if (c == '\\') {
218 ++table;
219 continue;
220 } else if (c == '=' || c == ';') {
221 break;
222 }
223 }
224 if (c == ';') {
225 table = tableKey;
226 } else {
227 eatThru('\"',&table);
228 }
229 *val = table;
230 *size = stringLength(table,0);
231 return YES;
232 }
233
234 eatThru(';',&table);
235
236 } while (*table);
237
238 return NO;
239}
240
241
242/*
243 * Returns a new malloc'ed string if one is found
244 * in the string table matching 'key'. Also translates
245 * \n escapes in the string.
246 */
247char *newStringForStringTableKey(
248 char *table,
249 char *key
250)
251{
252 char *val, *newstr, *p;
253 int size;
254
255 if (getValueForStringTableKey(table, key, &val, &size)) {
256 newstr = malloc(size+1);
257 for (p = newstr; size; size--, p++, val++) {
258 if ((*p = *val) == '\\') {
259 switch (*++val) {
260 case 'r':
261 *p = '\r';
262 break;
263 case 'n':
264 *p = '\n';
265 break;
266 case 't':
267 *p = '\t';
268 break;
269 default:
270 *p = *val;
271 break;
272 }
273 size--;
274 }
275 }
276 *p = '\0';
277 return newstr;
278 } else {
279 return 0;
280 }
281}
282
283char *
284newStringForKey(char *key)
285{
286 char *val, *newstr;
287 int size;
288
289 if (getValueForKey(key, &val, &size) && size) {
290 newstr = malloc(size + 1);
291 strncpy(newstr, val, size);
292 return newstr;
293 } else {
294 return 0;
295 }
296}
297
298/* parse a command line
299 * in the form: [<argument> ...] [<option>=<value> ...]
300 * both <option> and <value> must be either composed of
301 * non-whitespace characters, or enclosed in quotes.
302 */
303
304static char *getToken(char *line, char **begin, int *len)
305{
306 if (*line == '\"') {
307 *begin = ++line;
308 while (*line && *line != '\"')
309 line++;
310 *len = line++ - *begin;
311 } else {
312 *begin = line;
313 while (*line && !isspace(*line) && *line != '=')
314 line++;
315 *len = line - *begin;
316 }
317 return line;
318}
319
320BOOL getValueForBootKey(char *line, char *match, char **matchval, int *len)
321{
322 char *key, *value;
323 int key_len, value_len;
324
325 while (*line) {
326 /* look for keyword or argument */
327 while (isspace(*line)) line++;
328
329 /* now look for '=' or whitespace */
330 line = getToken(line, &key, &key_len);
331 /* line now points to '=' or space */
332 if (*line && !isspace(*line)) {
333 line = getToken(++line, &value, &value_len);
334 } else {
335 value = line;
336 value_len = 0;
337 }
338 if ((strlen(match) == key_len)
339 && strncmp(match, key, key_len) == 0) {
340 *matchval = value;
341 *len = value_len;
342 return YES;
343 }
344 }
345 return NO;
346}
347
348BOOL getBoolForKey(
349 char *key
350)
351{
352 char *val;
353 int size;
354
355 if (getValueForKey(key, &val, &size) && (size >= 1) &&
356 val[0] == 'Y' || val[0] == 'y')
357 return YES;
358 return NO;
359}
360
361BOOL getIntForKey(
362 char *key,
363 int *value
364)
365{
366 char *val;
367 int size, sum;
368
369 if (getValueForKey(key, &val, &size)) {
370 for (sum = 0; size > 0; size--) {
371 sum = (sum * 10) + (*val++ - '0');
372 }
373 *value = sum;
374 return YES;
375 }
376 return NO;
377}
378
379BOOL getValueForKey(
380 char *key,
381 char **val,
382 int *size
383)
384{
385 if (getValueForBootKey(kernBootStruct->bootString, key, val, size))
386 return YES;
387 else if (getValueForStringTableKey(kernBootStruct->config, key, val, size))
388 return YES;
389
390 return NO;
391}
392
393#if 0
394#define LOCALIZABLE_PATH \
395 "%s/%s.config/%s.lproj/%s.strings"
396char *
397loadLocalizableStrings(
398 char *name,
399 char *tableName
400)
401{
402 char buf[256], *config;
403 register int count, fd = -1;
404 char *device_dir = usrDevices();
405
406 sprintf(buf, LOCALIZABLE_PATH, device_dir, name,
407 Language, tableName);
408 if ((fd = open(buf, 0)) < 0) {
409 sprintf(buf, LOCALIZABLE_PATH, device_dir, name,
410 "English", tableName);
411 if ((fd = open(buf,0)) < 0) {
412 return 0;
413 }
414 }
415 count = file_size(fd);
416 config = malloc(count);
417 count = read(fd, config, count);
418 close(fd);
419 if (count <= 0) {
420 free(config);
421 return 0;
422 }
423 return config;
424}
425#endif
426
427#if 0 // XXX
428char *
429bundleLongName(
430 char *bundleName,
431 char *tableName
432)
433{
434 char *table, *name, *version, *newName;
435 char *path = malloc(256);
436
437#define LONG_NAME_FORMAT "%s (v%s)"
438 sprintf(path, "%s/%s.config/%s.table",
439 usrDevices(), bundleName, tableName ? tableName : "Default");
440 if (loadConfigFile(path, &table, YES) == 0) {
441 version = newStringForStringTableKey(table, "Version");
442 free(table);
443 } else {
444 version = newString("0.0");
445 }
446 table = loadLocalizableStrings(bundleName,
447 tableName ? tableName : "Localizable");
448 if (table) {
449 name = newStringForStringTableKey(table, "Long Name");
450 free(table);
451 } else {
452 name = newString(bundleName);
453 }
454 newName = malloc(strlen(name)+strlen(version)+strlen(LONG_NAME_FORMAT));
455 sprintf(newName, LONG_NAME_FORMAT, name, version);
456 free(name); free(version);
457 return newName;
458}
459#endif
460
461int sysConfigValid;
462
463void
464addConfig(
465 char *config
466)
467{
468 char *configPtr = kernBootStruct->configEnd;
469 int len = strlen(config);
470
471 if ((configPtr - kernBootStruct->config) > CONFIG_SIZE) {
472 error("No room in memory for config files\n");
473 return;
474 }
475 strcpy(configPtr, config);
476 configPtr += (len + 1);
477 *configPtr = 0;
478 kernBootStruct->configEnd = configPtr;
479}
480
481#define TABLE_EXPAND_SIZE 192
482
483/*
484 * Returns 0 if file loaded OK,
485 * -1 if file was not loaded
486 * Does not print error messages.
487 * Returns pointer to table in memory in *table.
488 * Allocates an extra number of bytes for table expansion.
489 */
490int
491loadConfigFile( char *configFile, char **table, BOOL allocTable)
492{
493 char *configPtr = kernBootStruct->configEnd;
494 int fd, count;
495
496 /* Read config file into memory */
497 if ((fd = open(configFile, 0)) >= 0)
498 {
499 if (allocTable) {
500 configPtr = malloc(file_size(fd)+2+TABLE_EXPAND_SIZE);
501 } else {
502 if ((configPtr - kernBootStruct->config) > CONFIG_SIZE) {
503 error("No room in memory for config files\n");
504 close(fd);
505 return -1;
506 }
507 verbose("Reading configuration file '%s'.\n",configFile);
508 }
509 if (table) *table = configPtr;
510 count = read(fd, configPtr, IO_CONFIG_DATA_SIZE);
511 close(fd);
512
513 configPtr += count;
514 *configPtr++ = 0;
515 *configPtr = 0;
516 if (!allocTable)
517 kernBootStruct->configEnd = configPtr;
518
519 return 0;
520 } else {
521 return -1;
522 }
523}
524
525/* Returns 0 if requested config files were loaded,
526 * 1 if default files were loaded,
527 * -1 if no files were loaded.
528 * Prints error message if files cannot be loaded.
529 */
530
531int
532loadConfigDir(
533 char *bundleName, // bundle directory name (e.g. "System")
534 BOOL useDefault, // use Default.table instead of instance tables
535 char **table, // returns pointer to config table
536 BOOL allocTable // malloc the table and return in *table
537)
538{
539 char *buf;
540 int i, max, ret;
541 char *device_dir = usrDevices();
542
543 buf = malloc(256);
544 ret = 0;
545
546 // load up to 99 instance tables
547 if (allocTable)
548 max = 1;
549 else
550 max = 99;
551 for (i=0; i < max; i++) {
552 sprintf(buf, "%s/%s.config/Instance%d.table",
553 device_dir,
554 bundleName, i);
555 if (useDefault || (loadConfigFile(buf, table, allocTable) != 0)) {
556 if (i == 0) {
557 // couldn't load first instance table;
558 // try the default table
559 sprintf(buf, "%s/%s.config/%s",
560 device_dir,
561 bundleName,
562 IO_DEFAULT_TABLE_FILENAME);
563 if (loadConfigFile(buf, table, allocTable) == 0) {
564 ret = 1;
565 } else {
566 if (!allocTable)
567 error("Config file \"%s\" not found\n", buf);
568 ret = -1;
569 }
570 }
571 // we must be done.
572 break;
573 }
574 }
575 free(buf);
576 return ret;
577}
578
579
580#define USR_SYSTEM_CONFIG \
581 USR_DEVICES "/System.config"
582#define USR_SYSTEM_DEFAULT_FILE \
583 USR_SYSTEM_CONFIG "/Default.table"
584#define ARCH_SYSTEM_CONFIG \
585 ARCH_DEVICES "/System.config"
586#define ARCH_SYSTEM_DEFAULT_FILE \
587 ARCH_SYSTEM_CONFIG "/Default.table"
588#define SYSTEM_CONFIG "System"
589#define LP '('
590#define RP ')'
591
592static int sysconfig_dev;
593
594/* Returns 0 if requested config files were loaded,
595 * 1 if default files were loaded,
596 * -1 if no files were loaded.
597 * Prints error message if files cannot be loaded.
598 */
599int
600loadSystemConfig(
601 char *which,
602 int size
603)
604{
605 char *buf, *bp, *cp;
606 int ret, len, doDefault=0;
607 char *device_dir = usrDevices();
608
609#if 0
610 printf("In Load system config which=%d ; size=%d\n", which, size);
611 //sleep(1);
612#endif 1
613 buf = bp = malloc(256);
614 if (which && size)
615 {
616#if 0
617 printf("In Load system config alt\n");
618 //sleep(1);
619#endif 1
620 for(cp = which, len = size; len && *cp && *cp != LP; cp++, len--) ;
621 if (*cp == LP) {
622 while (len-- && *cp && *cp++ != RP) ;
623 /* cp now points past device */
624 strncpy(buf,which,cp - which);
625 bp += cp - which;
626 } else {
627 cp = which;
628 len = size;
629 }
630 if (*cp != '/') {
631 strcpy(bp, device_dir);
632 strcat(bp, "/System.config/");
633 strncat(bp, cp, len);
634 if (strncmp(cp + len - strlen(IO_TABLE_EXTENSION),
635 IO_TABLE_EXTENSION, strlen(IO_TABLE_EXTENSION)) != 0)
636 strcat(bp, IO_TABLE_EXTENSION);
637 } else {
638 strncpy(bp, cp, len);
639 bp[size] = '\0';
640 }
641 if ((strcmp(bp, USR_SYSTEM_DEFAULT_FILE) == 0) ||
642 (strcmp(bp, ARCH_SYSTEM_DEFAULT_FILE) == 0))
643 doDefault = 1;
644 ret = loadConfigFile(bp = buf, 0, 0);
645 } else {
646#if 0
647 printf("In default SYSTEM_CONFIG LOAD\n");
648 //sleep(1);
649#endif 1
650 ret = loadConfigDir((bp = SYSTEM_CONFIG), 0, 0, 0);
651#if 0
652 printf("come back from SYSTEM_CONFIG loadConfigDir\n");
653 //sleep(1);
654#endif 1
655 }
656 sysconfig_dev = currentdev();
657 if (ret < 0) {
658 error("System config file '%s' not found\n", bp);
659 } else
660 sysConfigValid = 1;
661 free(buf);
662 return (ret < 0 ? ret : doDefault);
663}
664
665#ifdef DISABLED
666int
667loadOtherConfigs(
668 int useDefault
669)
670{
671 char *val, *table;
672 char *path = malloc(256);
673 char *hintTable;
674 char *installVersion = NULL, *thisVersion;
675 char *longName, *tableName;
676 int count;
677 char *string;
678 int ret;
679 int old_dev = currentdev();
680
681 if (sysconfig_dev)
682 switchdev(sysconfig_dev);
683 if (getValueForKey( "Boot Drivers", &val, &count))
684 {
685#if 0
686 printf("Loading Boot Drivers\n");
687 sleep(1);
688#endif 1
689 while (string = newStringFromList(&val, &count)) {
690 /* Check installation hints... */
691 sprintf(path, "%s/System.config/" INSTALL_HINTS
692 "/%s.table", usrDevices(), string);
693
694 if (getBoolForKey("Ignore Hints") == NO &&
695 loadConfigFile(path, &hintTable, YES) == 0) {
696 installVersion = newStringForStringTableKey(
697 hintTable, "Version");
698 longName = newStringForStringTableKey(
699 hintTable, "Long Name");
700 tableName = newStringForStringTableKey(
701 hintTable, "Default Table");
702 free(hintTable);
703 } else {
704 installVersion = longName = tableName = NULL;
705 }
706
707 ret = loadConfigDir(string, useDefault, &table, YES);
708 if (ret >= 0) {
709 thisVersion = newStringForStringTableKey(
710 table, "Version");
711 if (installVersion && thisVersion &&
712 (strcmp(thisVersion, installVersion) != 0)) {
713 /* Versions do not match */
714 driverIsMissing(string, installVersion, longName,
715 tableName, DRIVER_VERSION_MISMATCH);
716 } else {
717 struct driver_load_data dl;
718
719 dl.name = string;
720 if ((openDriverReloc(&dl)) >= 0) {
721 verbose("Loading binary for %s device driver.\n",string);
722 if (loadDriver(&dl) < 0) /// need to stop if error
723 error("Error loading %s device driver.\n",string);
724#if 0
725 printf("Calling link driver for %s\n", string);
726#endif 1
727 if (linkDriver(&dl) < 0)
728 error("Error linking %s device Driver.\n",string);
729 }
730 loadConfigDir(string, useDefault, NULL, NO);
731 driverWasLoaded(string, table, NULL);
732 free(table);
733 free(string);
734 free(installVersion); free(longName);
735 free(tableName);
736 }
737 free(thisVersion);
738 } else {
739 /* driver not found */
740 driverIsMissing(string, installVersion, longName,
741 tableName, DRIVER_NOT_FOUND);
742 }
743#if 0
744 if (ret == 1)
745 useDefault = 1; // use defaults from now on
746#endif
747 }
748 } else {
749 error("Warning: No Boot drivers specified in system config.\n");
750 }
751
752 kernBootStruct->first_addr0 =
753 (int)kernBootStruct->configEnd + 1024;
754 free(path);
755 switchdev(old_dev);
756 return 0;
757}
758#endif /* DISABLED */