2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Copyright 1993 NeXT, Inc.
27 * All rights reserved.
30 #include "bootstruct.h"
32 #include "stringConstants.h"
33 #include "legacy/configTablePrivate.h"
36 extern char *Language
;
37 extern char *LoadableFamilies
;
39 static TagPtr gConfigDict
;
41 static void eatThru(char val
, const char **table_p
);
43 static inline int isspace(char c
)
45 return (c
== ' ' || c
== '\t');
49 * Compare a string to a key with quoted characters
52 keyncmp(const char *str
, const char *key
, int n
)
71 } else if (c
== '\"') {
72 /* Premature end of key */
82 static void eatThru(char val
, const char **table_p
)
84 register const char *table
= *table_p
;
85 register BOOL found
= NO
;
87 while (*table
&& !found
)
89 if (*table
== '\\') table
+= 2;
92 if (*table
== val
) found
= YES
;
99 /* Remove key and its associated value from the table. */
102 removeKeyFromTable(const char *key
, char *table
)
110 buf
= (char *)malloc(len
+ 3);
112 sprintf(buf
, "\"%s\"", key
);
116 if(strncmp(buf
, tab
, len
) == 0) {
119 while((c
= *(tab
+ len
)) != ';') {
127 if(*(tab
+ len
) == '\n') len
++;
136 if(len
== -1) return NO
;
138 while((*tab
= *(tab
+ len
))) {
151 char *begin
= *list
, *end
;
156 while (*begin
&& newsize
&& isspace(*begin
)) {
161 while (*end
&& newsize
&& !isspace(*end
)) {
167 bufsize
= end
- begin
+ 1;
168 newstr
= malloc(bufsize
);
169 strlcpy(newstr
, begin
, bufsize
);
176 * compress == compress escaped characters to one character
178 int stringLength(const char *table
, int compress
)
187 ret
+= 1 + (compress
? 0 : 1);
191 if (*table
== '\"') return ret
;
199 BOOL
getValueForConfigTableKey(const char *table
, const char *key
, const char **val
, int *size
)
202 const char *tableKey
;
204 if (gConfigDict
!= 0 ) {
205 /* Look up key in XML dictionary */
207 value
= XMLGetProperty(gConfigDict
, key
);
209 if (value
->type
!= kTagTypeString
) {
210 error("Non-string tag '%s' found in config file\n",
214 *val
= value
->string
;
215 *size
= strlen(value
->string
);
219 /* Legacy plist-style table */
222 eatThru('\"',&table
);
224 keyLength
= strlen(key
);
226 (stringLength(table
,1) == keyLength
) &&
227 (keyncmp(key
, table
, keyLength
) == 0))
231 /* found the key; now look for either
239 } else if (c
== '=' || c
== ';') {
246 eatThru('\"',&table
);
249 *size
= stringLength(table
,0);
262 * Returns a new malloc'ed string if one is found
263 * in the string table matching 'key'. Also translates
264 * \n escapes in the string.
266 char *newStringForStringTableKey(
275 if (getValueForConfigTableKey(table
, key
, &val
, &size
)) {
276 newstr
= (char *)malloc(size
+1);
277 for (p
= newstr
; size
; size
--, p
++, val
++) {
278 if ((*p
= *val
) == '\\') {
304 newStringForKey(char *key
)
310 if (getValueForKey(key
, &val
, &size
) && size
) {
311 newstr
= (char *)malloc(size
+ 1);
312 strlcpy(newstr
, val
, size
+ 1);
319 /* parse a command line
320 * in the form: [<argument> ...] [<option>=<value> ...]
321 * both <option> and <value> must be either composed of
322 * non-whitespace characters, or enclosed in quotes.
325 static const char *getToken(const char *line
, const char **begin
, int *len
)
329 while (*line
&& *line
!= '\"')
331 *len
= line
++ - *begin
;
334 while (*line
&& !isspace(*line
) && *line
!= '=')
336 *len
= line
- *begin
;
341 BOOL
getValueForBootKey(const char *line
, const char *match
, const char **matchval
, int *len
)
343 const char *key
, *value
;
344 int key_len
, value_len
;
347 /* look for keyword or argument */
348 while (isspace(*line
)) line
++;
350 /* now look for '=' or whitespace */
351 line
= getToken(line
, &key
, &key_len
);
352 /* line now points to '=' or space */
353 if (*line
&& !isspace(*line
)) {
354 line
= getToken(++line
, &value
, &value_len
);
359 if ((strlen(match
) == key_len
)
360 && strncmp(match
, key
, key_len
) == 0) {
376 if (getValueForKey(key
, &val
, &size
) && (size
>= 1) &&
377 val
[0] == 'Y' || val
[0] == 'y')
390 if (getValueForKey(key
, &val
, &size
)) {
391 for (sum
= 0; size
> 0; size
--) {
392 sum
= (sum
* 10) + (*val
++ - '0');
406 if (getValueForBootKey(bootArgs
->bootString
, key
, val
, size
))
408 else if (getValueForConfigTableKey(bootArgs
->config
, key
, val
, size
))
416 #define TABLE_EXPAND_SIZE 192
419 * Returns 0 if file loaded OK,
420 * -1 if file was not loaded
421 * Does not print error messages.
422 * Returns pointer to table in memory in *table.
423 * Allocates an extra number of bytes for table expansion.
426 loadConfigFile(const char *configFile
, const char **table
, BOOL allocTable
)
428 char *configPtr
= bootArgs
->configEnd
;
431 /* Read config file into memory */
432 if ((fd
= open(configFile
, 0)) >= 0)
435 configPtr
= malloc(file_size(fd
)+2+TABLE_EXPAND_SIZE
);
437 if ((configPtr
- bootArgs
->config
) > CONFIG_SIZE
) {
438 error("No room in memory for config files\n");
442 verbose("Reading configuration file '%s'.\n",configFile
);
444 if (table
) *table
= configPtr
;
445 count
= read(fd
, configPtr
, IO_CONFIG_DATA_SIZE
);
452 bootArgs
->configEnd
= configPtr
;
460 /* Returns 0 if requested config files were loaded,
461 * 1 if default files were loaded,
462 * -1 if no files were loaded.
463 * Prints error message if files cannot be loaded.
468 const char *bundleName
, // bundle directory name (e.g. "System")
469 BOOL useDefault
, // use Default.table instead of instance tables
470 const char **table
, // returns pointer to config table
471 BOOL allocTable
// malloc the table and return in *table
476 const char *device_dir
= usrDevices();
481 // load up to 99 instance tables
486 for (i
=0; i
< max
; i
++) {
487 sprintf(buf
, "%s/%s.config/Instance%d.table",
490 if (useDefault
|| (loadConfigFile(buf
, table
, allocTable
) != 0)) {
492 // couldn't load first instance table;
493 // try the default table
494 sprintf(buf
, "%s/%s.config/%s",
497 IO_DEFAULT_TABLE_FILENAME
);
498 if (loadConfigFile(buf
, table
, allocTable
) == 0) {
502 error("Config file \"%s\" not found\n", buf
);
503 sleep(1); // let the message be seen!
517 #define USR_SYSTEM_CONFIG \
518 USR_DEVICES "/System.config"
519 #define USR_SYSTEM_DEFAULT_FILE \
520 USR_SYSTEM_CONFIG "/Default.table"
521 #define ARCH_SYSTEM_CONFIG \
522 ARCH_DEVICES "/System.config"
523 #define ARCH_SYSTEM_DEFAULT_FILE \
524 ARCH_SYSTEM_CONFIG "/Default.table"
525 #define SYSTEM_CONFIG "System"
529 #define SYSTEM_CONFIG_DIR "/Library/Preferences/SystemConfiguration"
530 #define SYSTEM_CONFIG_FILE "/com.apple.Boot.plist"
531 #define SYSTEM_CONFIG_PATH SYSTEM_CONFIG_DIR SYSTEM_CONFIG_FILE
532 #define CONFIG_EXT ".plist"
536 printSystemConfig(void)
538 char *p1
= bootArgs
->config
;
541 while (*p1
!= '\0') {
542 while (*p2
!= '\0' && *p2
!= '\n') p2
++;
547 if (tmp
== '\0') break;
553 static int sysconfig_dev
;
555 //==========================================================================
557 // Modifies the input buffer.
558 // Expects to see one dictionary in the XML file.
559 // Puts the first dictionary it finds in the
560 // tag pointer and returns 0, or returns -1 if not found
561 // (and does not modify dict pointer).
564 ParseXMLFile( char * buffer
, TagPtr
* dict
)
571 configBuffer
= malloc(strlen(buffer
)+1);
572 strcpy(configBuffer
, buffer
);
576 length
= XMLParseNextTag(configBuffer
+ pos
, &tag
);
577 if (length
== -1) break;
581 if (tag
== 0) continue;
582 if (tag
->type
== kTagTypeDict
) break;
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.
607 int ret
, len
, doDefault
=0;
609 buf
= bp
= malloc(512);
611 for(cp
= which
, len
= size
; len
&& *cp
&& *cp
!= LP
; cp
++, len
--) ;
613 while (len
-- && *cp
&& *cp
++ != RP
) ;
614 /* cp now points past device */
615 strlcpy(buf
,which
,cp
- which
);
622 strcpy(bp
, systemConfigDir());
624 strncat(bp
, cp
, len
);
625 if (strncmp(cp
+ len
- strlen(CONFIG_EXT
),
626 CONFIG_EXT
, strlen(CONFIG_EXT
)) != 0)
627 strcat(bp
, CONFIG_EXT
);
629 strlcpy(bp
, cp
, len
);
631 if ((strcmp(bp
, SYSTEM_CONFIG_PATH
) == 0)) {
634 ret
= loadConfigFile(bp
= buf
, 0, 0);
636 strcpy(bp
, systemConfigDir());
637 strcat(bp
, SYSTEM_CONFIG_FILE
);
638 ret
= loadConfigFile(bp
, 0, 0);
640 ret
= loadConfigDir((bp
= SYSTEM_CONFIG
), 0, 0, 0);
643 sysconfig_dev
= currentdev();
645 error("System config file '%s' not found\n", bp
);
649 // Check for XML file;
650 // if not XML, gConfigDict will remain 0.
651 ParseXMLFile(bootArgs
->config
, &gConfigDict
);
654 return (ret
< 0 ? ret
: doDefault
);
658 char * newString(const char * oldString
)
661 return strcpy(malloc(strlen(oldString
)+1), oldString
);