diff options
author | wkoszek <wkoszek@FreeBSD.org> | 2007-05-12 19:38:18 +0000 |
---|---|---|
committer | wkoszek <wkoszek@FreeBSD.org> | 2007-05-12 19:38:18 +0000 |
commit | 2e673327ec1ac7c1b4a99f2bfe326756e0547067 (patch) | |
tree | 7df0bae947c0e7aa57e02e7373440d236848d9d0 /usr.sbin/config/config.y | |
parent | a0d76ca625afcd4dd4e8a520e6855ba3b9bc2c96 (diff) | |
download | FreeBSD-src-2e673327ec1ac7c1b4a99f2bfe326756e0547067.zip FreeBSD-src-2e673327ec1ac7c1b4a99f2bfe326756e0547067.tar.gz |
Improve INCLUDE_CONFIG_FILE support.
This change will let us to have full configuration of a running kernel
available in sysctl:
sysctl -b kern.conftxt
The same configuration is also contained within the kernel image. It can be
obtained with:
config -x <kernelfile>
Current functionality lets you to quickly recover kernel configuration, by
simply redirecting output from commands presented above and starting kernel
build procedure. "include" statements are also honored, which means options
and devices from included files are also included.
Please note that comments from configuration files are not preserved by
default. In order to preserve them, you can use -C flag for config(8). This
will bring configuration file and included files literally; however,
redirection to a file no longer works directly.
This commit was followed by discussion, that took place on freebsd-current@.
For more details, look here:
http://lists.freebsd.org/pipermail/freebsd-current/2007-March/069994.html
http://lists.freebsd.org/pipermail/freebsd-current/2007-May/071844.html
Development of this patch took place in Perforce, hierarchy:
//depot/user/wkoszek/wkoszek_kconftxt/
Support from: freebsd-current@ (links above)
Reviewed by: imp@
Approved by: imp@
Diffstat (limited to 'usr.sbin/config/config.y')
-rw-r--r-- | usr.sbin/config/config.y | 109 |
1 files changed, 82 insertions, 27 deletions
diff --git a/usr.sbin/config/config.y b/usr.sbin/config/config.y index 40ee93d..9c8ba39 100644 --- a/usr.sbin/config/config.y +++ b/usr.sbin/config/config.y @@ -70,6 +70,7 @@ * $FreeBSD$ */ +#include <assert.h> #include <ctype.h> #include <err.h> #include <stdio.h> @@ -77,7 +78,7 @@ #include "config.h" -struct device_head dtab; +struct device_head dtab, rmdtab; char *ident; char *env; int envmode; @@ -104,6 +105,9 @@ devopt(char *dev) return ret; } +static void rmoptall(struct opt_head *list, struct opt_head *torem); +static void rmdevall(struct device_head *dh, struct device_head *torem); + %} %% Configuration: @@ -122,7 +126,10 @@ Spec: Config_spec SEMICOLON | INCLUDE ID SEMICOLON - = { include($2, 0); }; + = { + if (incignore == 0) + include($2, 0); + }; | FILES ID SEMICOLON = { newfile($2); }; @@ -170,11 +177,11 @@ Config_spec: OPTIONS Opt_list | NOOPTION Save_id - = { rmopt(&opt, $2); } | + = { rmopt_schedule(&rmopts, $2); } | MAKEOPTIONS Mkopt_list | NOMAKEOPTION Save_id - = { rmopt(&mkopt, $2); } | + = { rmopt_schedule(&mkopt, $2); } | IDENT ID = { ident = $2; } | System_spec @@ -298,10 +305,10 @@ NoDevice: = { char *s = devopt($1); - rmopt(&opt, s); + rmopt_schedule(&rmopts, s); free(s); /* and the device part */ - rmdev($1); + rmdev_schedule(&rmdtab, $1); } ; %% @@ -317,14 +324,16 @@ int yywrap(void) { - if (found_defaults) { - if (freopen(PREFIX, "r", stdin) == NULL) - err(2, "%s", PREFIX); - yyfile = PREFIX; + if (found_defaults == 0 && incignore == 0) { + if (freopen("DEFAULTS", "r", stdin) == NULL) + return 1; + yyfile = "DEFAULTS"; yyline = 0; - found_defaults = 0; + found_defaults = 1; return 0; } + rmoptall(&opt, &rmopts); + rmdevall(&dtab, &rmdtab); return 1; } @@ -345,11 +354,11 @@ newfile(char *name) * Find a device in the list of devices. */ static struct device * -finddev(char *name) +finddev(struct device_head *dlist, char *name) { struct device *dp; - STAILQ_FOREACH(dp, &dtab, d_next) + STAILQ_FOREACH(dp, dlist, d_next) if (eq(dp->d_name, name)) return (dp); @@ -364,7 +373,7 @@ newdev(char *name) { struct device *np; - if (finddev(name)) { + if (finddev(&dtab, name)) { printf("WARNING: duplicate device `%s' encountered.\n", name); return; } @@ -375,17 +384,36 @@ newdev(char *name) } /* - * Remove a device from the list of devices. + * Schedule a device to removal. */ static void -rmdev(char *name) +rmdev_schedule(struct device_head *dh, char *name) { struct device *dp; - dp = finddev(name); - if (dp != NULL) { - STAILQ_REMOVE(&dtab, dp, device, d_next); - free(dp->d_name); + dp = calloc(1, sizeof(struct device)); + dp->d_name = strdup(name); + assert(dp->d_name != NULL); + STAILQ_INSERT_HEAD(dh, dp, d_next); +} + +/* + * Take care a devices previously scheduled for removal. + */ +static void +rmdevall(struct device_head *dh, struct device_head *torem) +{ + struct device *dp, *rdp; + + while (!STAILQ_EMPTY(torem)) { + dp = STAILQ_FIRST(torem); + STAILQ_REMOVE_HEAD(torem, d_next); + rdp = finddev(dh, dp->d_name); + if (rdp != NULL) { + STAILQ_REMOVE(dh, rdp, device, d_next); + free(rdp->d_name); + free(rdp); + } free(dp); } } @@ -413,6 +441,14 @@ newopt(struct opt_head *list, char *name, char *value) { struct opt *op; + /* + * Ignore inclusions listed explicitly for configuration files. + */ + if (eq(name, OPT_AUTOGEN)) { + incignore = 1; + return; + } + if (findopt(list, name)) { printf("WARNING: duplicate option `%s' encountered.\n", name); return; @@ -429,16 +465,35 @@ newopt(struct opt_head *list, char *name, char *value) * Remove an option from the list of options. */ static void -rmopt(struct opt_head *list, char *name) +rmopt_schedule(struct opt_head *list, char *name) { struct opt *op; - op = findopt(list, name); - if (op != NULL) { - SLIST_REMOVE(list, op, opt, op_next); - free(op->op_name); - if (op->op_value != NULL) - free(op->op_value); + op = calloc(1, sizeof(*op)); + op->op_name = ns(name); + SLIST_INSERT_HEAD(list, op, op_next); +} + +/* + * Remove all options that were scheduled for removal. + */ +static void +rmoptall(struct opt_head *list, struct opt_head *torem) +{ + struct opt *op, *rop; + + op = rop = NULL; + while (!SLIST_EMPTY(torem)) { + op = SLIST_FIRST(torem); + SLIST_REMOVE_HEAD(torem, op_next); + rop = findopt(list, op->op_name); + if (rop != NULL) { + SLIST_REMOVE(list, rop, opt, op_next); + free(rop->op_name); + if (rop->op_value != NULL) + free(rop->op_value); + free(rop); + } free(op); } } |