summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_mib.c33
-rw-r--r--usr.sbin/config/Makefile9
-rw-r--r--usr.sbin/config/config.842
-rw-r--r--usr.sbin/config/config.h27
-rw-r--r--usr.sbin/config/config.y109
-rw-r--r--usr.sbin/config/kernconf.tmpl17
-rw-r--r--usr.sbin/config/lang.l26
-rw-r--r--usr.sbin/config/main.c249
8 files changed, 422 insertions, 90 deletions
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index 0a5220d..2ccb207 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
+#include <sys/sbuf.h>
#include <sys/systm.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
@@ -295,6 +296,38 @@ SYSCTL_PROC(_kern, KERN_SECURELVL, securelevel,
CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0, sysctl_kern_securelvl,
"I", "Current secure level");
+/* Actual kernel configuration options. */
+extern char kernconfstring[];
+
+static int
+sysctl_kern_config(SYSCTL_HANDLER_ARGS)
+{
+ struct sbuf *sb;
+ int error;
+ char *p;
+
+ sb = sbuf_new(NULL, NULL, 2048, SBUF_AUTOEXTEND);
+ if (sb == NULL)
+ return (ENOMEM);
+ sbuf_clear(sb);
+ p = kernconfstring;
+ if (p == NULL || *p == '\0') {
+ sbuf_printf(sb, "No kernel configuration\n");
+ } else {
+ sbuf_printf(sb, "%s", p);
+ }
+ sbuf_trim(sb);
+ sbuf_putc(sb, '\n');
+ sbuf_finish(sb);
+ error = sysctl_handle_string(oidp, sbuf_data(sb), sbuf_len(sb), req);
+ if (error)
+ return (error);
+ sbuf_delete(sb);
+ return (error);
+}
+SYSCTL_PROC(_kern, OID_AUTO, conftxt, CTLTYPE_STRING|CTLFLAG_RW,
+ 0, 0, sysctl_kern_config, "", "Kernel configuration file");
+
char domainname[MAXHOSTNAMELEN];
SYSCTL_STRING(_kern, KERN_NISDOMAINNAME, domainname, CTLFLAG_RW,
&domainname, sizeof(domainname), "Name of the current YP/NIS domain");
diff --git a/usr.sbin/config/Makefile b/usr.sbin/config/Makefile
index 8861b3c..bd318ae 100644
--- a/usr.sbin/config/Makefile
+++ b/usr.sbin/config/Makefile
@@ -4,13 +4,18 @@
PROG= config
MAN= config.5 config.8
SRCS= config.y main.c lang.l mkmakefile.c mkheaders.c \
- mkoptions.c y.tab.h
+ mkoptions.c y.tab.h kernconf.c
+
+kernconf.c: kernconf.tmpl
+ file2c 'char kernconfstr[] = {' ',0};' < kernconf.tmpl > kernconf.c
WARNS?= 6
CFLAGS+= -I. -I${.CURDIR}
DPADD= ${LIBL}
-LDADD= -ll
+LDADD= -ll -lsbuf
+
+CLEANFILES+= kernconf.c
mkmakefile.o: configvers.h
diff --git a/usr.sbin/config/config.8 b/usr.sbin/config/config.8
index adffa12..01abc94 100644
--- a/usr.sbin/config/config.8
+++ b/usr.sbin/config/config.8
@@ -28,7 +28,7 @@
.\" @(#)config.8 8.2 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd December 16, 2004
+.Dd May 8, 2007
.Dt CONFIG 8
.Os
.Sh NAME
@@ -36,9 +36,11 @@
.Nd build system configuration files
.Sh SYNOPSIS
.Nm
-.Op Fl Vgp
+.Op Fl CVgp
.Op Fl d Ar destdir
.Ar SYSTEM_NAME
+.Nm
+.Op Fl x Ar kernel
.Sh DESCRIPTION
.\" This is the old version of the
.\" .Nm
@@ -76,6 +78,11 @@ Available options and operands:
Print the
.Nm
version number.
+.It Fl C
+If the INCLUDE_CONFIG_FILE is present in a configuration file,
+kernel image will contain full configuration files included
+literally (preserving comments).
+This flag is kept for backward compatibility.
.It Fl d Ar destdir
Use
.Ar destdir
@@ -87,6 +94,12 @@ does not append
to the directory given.
.It Fl g
Configure a system for debugging.
+.It Fl x Ar kernel
+Print kernel configuration file embedded into a kernel
+file.
+This option makes sense only if
+.Cd "options INCLUDE_CONFIG_FILE"
+entry was present in your configuration file.
.It Fl p
Configure a system for profiling; for example,
.Xr kgmon 8
@@ -151,17 +164,6 @@ the problems in the configuration file should be corrected and
should be run again.
Attempts to compile a system that had configuration errors
are likely to fail.
-.Pp
-If the
-.Cd "options INCLUDE_CONFIG_FILE"
-is used in the configuration file the
-entire input file is embedded in the new kernel.
-This means that
-.Xr strings 1
-can be used to extract it from a kernel:
-to extract the configuration information, use the command
-.Pp
-.Dl "strings -n 3 kernel | sed -n 's/^___//p'"
.Sh DEBUG KERNELS
Traditional
.Bx
@@ -254,5 +256,19 @@ The
.Nm
utility appeared in
.Bx 4.1 .
+.Pp
+Before support for
+.Fl x
+was introduced,
+.Cd "options INCLUDE_CONFIG_FILE"
+included entire configuration file that used to be embedded in
+the new kernel.
+This meant that
+.Xr strings 1
+could be used to extract it from a kernel:
+to extract the configuration information, you had to use
+the command:
+.Pp
+.Dl "strings -n 3 kernel | sed -n 's/^___//p'"
.Sh BUGS
The line numbers reported in error messages are usually off by one.
diff --git a/usr.sbin/config/config.h b/usr.sbin/config/config.h
index 08ac796..3a32520 100644
--- a/usr.sbin/config/config.h
+++ b/usr.sbin/config/config.h
@@ -38,6 +38,12 @@
#include <stdlib.h>
#include <string.h>
+struct cfgfile {
+ STAILQ_ENTRY(cfgfile) cfg_next;
+ char *cfg_path;
+};
+STAILQ_HEAD(, cfgfile) cfgfiles;
+
struct file_list {
STAILQ_ENTRY(file_list) f_next;
char *f_fn; /* the name */
@@ -117,7 +123,7 @@ struct opt {
SLIST_ENTRY(opt) op_next;
};
-SLIST_HEAD(opt_head, opt) opt, mkopt;
+SLIST_HEAD(opt_head, opt) opt, mkopt, rmopts;
struct opt_list {
char *o_name;
@@ -134,11 +140,26 @@ struct hint {
STAILQ_HEAD(hint_head, hint) hints;
+/*
+ * Tag present in the kernelconf.tmlp template file. It's mandatory for those
+ * two strings to be the same. Otherwise you'll get into trouble.
+ */
+#define KERNCONFTAG "%%KERNCONFFILE%%"
+
+/*
+ * Faked option to note, that the configuration file has been taken from the
+ * kernel file and inclusion of DEFAULTS etc.. isn't nessesery, because we
+ * already have a list of all required devices.
+ */
+#define OPT_AUTOGEN "CONFIG_AUTOGENERATED"
+
extern char *ident;
extern char *env;
+extern char kernconfstr[];
extern int do_trace;
extern int envmode;
extern int hintmode;
+extern int incignore;
char *get_word(FILE *);
char *get_quoted_word(FILE *);
@@ -153,8 +174,10 @@ void makefile(void);
void makeenv(void);
void makehints(void);
void headers(void);
+void cfgfile_add(const char *);
+void cfgfile_removeall(void);
-extern STAILQ_HEAD(device_head, device) dtab;
+extern STAILQ_HEAD(device_head, device) dtab, rmdtab;
extern char errbuf[80];
extern int yyline;
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);
}
}
diff --git a/usr.sbin/config/kernconf.tmpl b/usr.sbin/config/kernconf.tmpl
new file mode 100644
index 0000000..981efb7
--- /dev/null
+++ b/usr.sbin/config/kernconf.tmpl
@@ -0,0 +1,17 @@
+/*
+ * This file acts as a template for config.c that will be generated in the
+ * kernel build directory after config(8) has been successfully run.
+ *
+ * $FreeBSD$
+ */
+#include "opt_config.h"
+#ifdef INCLUDE_CONFIG_FILE
+
+const char kernconfstring[] __attribute__ ((section("kern_conf"))) =
+"%%KERNCONFFILE%%";
+
+#else
+
+const char kernconfstring[] = "\0";
+
+#endif /* INCLUDE_CONFIG_FILE */
diff --git a/usr.sbin/config/lang.l b/usr.sbin/config/lang.l
index 4eb0de7..2f2886e 100644
--- a/usr.sbin/config/lang.l
+++ b/usr.sbin/config/lang.l
@@ -207,6 +207,30 @@ hex(const char *str)
return num;
}
+void
+cfgfile_add(const char *fname)
+{
+ struct cfgfile *cf;
+
+ cf = calloc(1, sizeof(*cf));
+ assert(cf != NULL);
+ asprintf(&cf->cfg_path, "%s", fname);
+ STAILQ_INSERT_TAIL(&cfgfiles, cf, cfg_next);
+}
+
+void
+cfgfile_removeall(void)
+{
+ struct cfgfile *cf;
+
+ while (!STAILQ_EMPTY(&cfgfiles)) {
+ cf = STAILQ_FIRST(&cfgfiles);
+ STAILQ_REMOVE_HEAD(&cfgfiles, cfg_next);
+ if (cf->cfg_path != NULL)
+ free(cf->cfg_path);
+ free(cf);
+ }
+}
/*
* Open the named file for inclusion at the current point. Returns 0 on
@@ -222,6 +246,7 @@ include(const char *fname, int ateof)
struct incl *in;
char *fnamebuf;
+ fnamebuf = NULL;
fp = fopen(fname, "r");
if (fp == NULL && fname[0] != '.' && fname[0] != '/') {
asprintf(&fnamebuf, "../../conf/%s", fname);
@@ -234,6 +259,7 @@ include(const char *fname, int ateof)
yyerror("cannot open included file");
return (-1);
}
+ cfgfile_add(fnamebuf == NULL ? fname : fnamebuf);
in = malloc(sizeof(*in));
assert(in != NULL);
in->in_prev = inclp;
diff --git a/usr.sbin/config/main.c b/usr.sbin/config/main.c
index f9d2322..aede132 100644
--- a/usr.sbin/config/main.c
+++ b/usr.sbin/config/main.c
@@ -43,9 +43,12 @@ static const char rcsid[] =
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/sbuf.h>
#include <sys/file.h>
#include <sys/mman.h>
#include <sys/param.h>
+
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <stdio.h>
@@ -73,11 +76,19 @@ char srcdir[MAXPATHLEN];
int debugging;
int profiling;
int found_defaults;
+int incignore;
+
+/*
+ * Preserve old behaviour in INCLUDE_CONFIG_FILE handling (files are included
+ * literally).
+ */
+int filebased = 0;
static void configfile(void);
static void get_srcdir(void);
static void usage(void);
static void cleanheaders(char *);
+static void kernconfdump(const char *);
struct hdr_list {
char *h_name;
@@ -96,13 +107,14 @@ main(int argc, char **argv)
int ch, len;
char *p;
char xxx[MAXPATHLEN];
- FILE *fp;
+ char *kernfile;
- while ((ch = getopt(argc, argv, "d:gpV")) != -1)
+ kernfile = NULL;
+ while ((ch = getopt(argc, argv, "Cd:gpVx:")) != -1)
switch (ch) {
- case 'V':
- printf("%d\n", CONFIGVERS);
- exit(0);
+ case 'C':
+ filebased = 1;
+ break;
case 'd':
if (*destdir == '\0')
strlcpy(destdir, optarg, sizeof(destdir));
@@ -115,6 +127,12 @@ main(int argc, char **argv)
case 'p':
profiling++;
break;
+ case 'V':
+ printf("%d\n", CONFIGVERS);
+ exit(0);
+ case 'x':
+ kernfile = optarg;
+ break;
case '?':
default:
usage();
@@ -122,23 +140,23 @@ main(int argc, char **argv)
argc -= optind;
argv += optind;
+ if (kernfile != NULL) {
+ kernconfdump(kernfile);
+ exit(EXIT_SUCCESS);
+ }
+
if (argc != 1)
usage();
PREFIX = *argv;
- fp = fopen(PREFIX, "r");
- if (fp == NULL)
+ /*
+ * We mark lack of DEFAULTS here. Once we hit EOF in PREFIX, yywrap()
+ * will try to bring DEFAULTS to the playground, if this exists.
+ */
+ found_defaults = 0;
+ if (freopen(PREFIX, "r", stdin) == NULL)
err(2, "%s", PREFIX);
- fclose(fp);
- if (freopen("DEFAULTS", "r", stdin) != NULL) {
- found_defaults = 1;
- yyfile = "DEFAULTS";
- } else {
- if (freopen(PREFIX, "r", stdin) == NULL)
- err(2, "%s", PREFIX);
- yyfile = PREFIX;
- }
-
+ yyfile = PREFIX;
if (*destdir != '\0') {
len = strlen(destdir);
while (len > 1 && destdir[len - 1] == '/')
@@ -156,11 +174,16 @@ main(int argc, char **argv)
} else if (!S_ISDIR(buf.st_mode))
errx(2, "%s isn't a directory", p);
+ SLIST_INIT(&cputype);
+ SLIST_INIT(&mkopt);
+ SLIST_INIT(&opt);
+ SLIST_INIT(&rmopts);
+ STAILQ_INIT(&cfgfiles);
STAILQ_INIT(&dtab);
STAILQ_INIT(&fntab);
- SLIST_INIT(&cputype);
STAILQ_INIT(&ftab);
STAILQ_INIT(&hints);
+ STAILQ_INIT(&rmdtab);
if (yyparse())
exit(3);
@@ -206,12 +229,12 @@ main(int argc, char **argv)
(void) unlink(path(machinearch));
(void) symlink(xxx, path(machinearch));
}
+ configfile(); /* put config file into kernel*/
options(); /* make options .h files */
makefile(); /* build Makefile */
makeenv(); /* build env.c */
makehints(); /* build hints.c */
headers(); /* make a lot of .h files */
- configfile(); /* put config file into kernel*/
cleanheaders(p);
printf("Kernel build directory is %s\n", p);
printf("Don't forget to do ``make cleandepend && make depend''\n");
@@ -235,8 +258,9 @@ static void
usage(void)
{
- fprintf(stderr, "usage: config [-Vgp] [-d destdir] sysname\n");
- exit(1);
+ fprintf(stderr, "usage: config [-CgpV] [-d destdir] sysname\n");
+ fprintf(stderr, " config -x kernel\n");
+ exit(EX_USAGE);
}
/*
@@ -362,40 +386,119 @@ path(const char *file)
return (cp);
}
+/*
+ * Generate configuration file based on actual settings. With this mode, user
+ * will be able to obtain and build conifguration file with one command.
+ */
+static void
+configfile_dynamic(struct sbuf *sb)
+{
+ struct cputype *cput;
+ struct device *d;
+ struct opt *ol;
+ char *lend;
+
+ asprintf(&lend, "\\n\\\n");
+ assert(lend != NULL);
+ sbuf_printf(sb, "options\t%s%s", OPT_AUTOGEN, lend);
+ sbuf_printf(sb, "ident\t%s%s", ident, lend);
+ sbuf_printf(sb, "machine\t%s%s", machinename, lend);
+ SLIST_FOREACH(cput, &cputype, cpu_next)
+ sbuf_printf(sb, "cpu\t%s%s", cput->cpu_name, lend);
+ SLIST_FOREACH(ol, &mkopt, op_next)
+ sbuf_printf(sb, "makeoptions\t%s=%s%s", ol->op_name,
+ ol->op_value, lend);
+ SLIST_FOREACH(ol, &opt, op_next) {
+ if (strncmp(ol->op_name, "DEV_", 4) == 0)
+ continue;
+ sbuf_printf(sb, "options\t%s", ol->op_name);
+ if (ol->op_value != NULL) {
+ sbuf_printf(sb, "=%s%s", ol->op_value, lend);
+ } else {
+ sbuf_printf(sb, "%s", lend);
+ }
+ }
+ /*
+ * Mark this file as containing everything we need.
+ */
+ STAILQ_FOREACH(d, &dtab, d_next)
+ sbuf_printf(sb, "device\t%s%s", d->d_name, lend);
+ free(lend);
+}
+
+/*
+ * Generate file from the configuration files.
+ */
+static void
+configfile_filebased(struct sbuf *sb)
+{
+ FILE *cff;
+ struct cfgfile *cf;
+ int i;
+
+ STAILQ_FOREACH(cf, &cfgfiles, cfg_next) {
+ cff = fopen(cf->cfg_path, "r");
+ if (cff == NULL) {
+ warn("Couldn't open file %s", cf->cfg_path);
+ continue;
+ }
+ while ((i = getc(cff)) != EOF) {
+ if (i == '\n')
+ sbuf_printf(sb, "\\n\\\n");
+ else if (i == '"' || i == '\'')
+ sbuf_printf(sb, "\\%c", i);
+ else
+ sbuf_putc(sb, i);
+ }
+ fclose(cff);
+ }
+}
+
static void
configfile(void)
{
- FILE *fi, *fo;
+ FILE *fo;
+ struct sbuf *sb;
char *p;
- int i;
-
- fi = fopen(PREFIX, "r");
- if (!fi)
- err(2, "%s", PREFIX);
- fo = fopen(p=path("config.c.new"), "w");
+
+ /* Add main configuration file to the list of files to be included */
+ cfgfile_add(PREFIX);
+ p = path("config.c.new");
+ fo = fopen(p, "w");
if (!fo)
err(2, "%s", p);
- fprintf(fo, "#include \"opt_config.h\"\n");
- fprintf(fo, "#ifdef INCLUDE_CONFIG_FILE \n");
- fprintf(fo, "const char config[] = \"\\\n");
- fprintf(fo, "START CONFIG FILE %s\\n\\\n___", PREFIX);
- while (EOF != (i=getc(fi))) {
- if (i == '\n') {
- fprintf(fo, "\\n\\\n___");
- } else if (i == '\"') {
- fprintf(fo, "\\\"");
- } else if (i == '\\') {
- fprintf(fo, "\\\\");
- } else {
- putc(i, fo);
- }
+ sb = sbuf_new(NULL, NULL, 2048, SBUF_AUTOEXTEND);
+ assert(sb != NULL);
+ sbuf_clear(sb);
+ /*
+ * Try to read all configuration files. Since those will be present as
+ * C string in the macro, we have to slash their ends then the line
+ * wraps.
+ */
+ if (filebased) {
+ /* Is needed, can be used for backward compatibility. */
+ configfile_filebased(sb);
+ } else {
+ configfile_dynamic(sb);
}
- fprintf(fo, "\\n\\\nEND CONFIG FILE %s\\n\\\n", PREFIX);
- fprintf(fo, "\";\n");
- fprintf(fo, "\n#endif /* INCLUDE_CONFIG_FILE */\n");
- fclose(fi);
+ sbuf_finish(sb);
+ /*
+ * We print first part of the tamplate, replace our tag with
+ * configuration files content and later continue writing our
+ * template.
+ */
+ p = strstr(kernconfstr, KERNCONFTAG);
+ if (p == NULL)
+ errx(EXIT_FAILURE, "Something went terribly wrong!");
+ *p = '\0';
+ fprintf(fo, "%s", kernconfstr);
+ fprintf(fo, "%s", sbuf_data(sb));
+ p += strlen(KERNCONFTAG);
+ fprintf(fo, "%s", p);
+ sbuf_delete(sb);
fclose(fo);
moveifchanged(path("config.c.new"), path("config.c"));
+ cfgfile_removeall();
}
/*
@@ -524,3 +627,57 @@ remember(const char *file)
hl->h_next = htab;
htab = hl;
}
+
+/*
+ * This one is quick hack. Will be probably moved to elf(3) interface.
+ * It takes kernel configuration file name, passes it as an argument to
+ * elfdump -a, which output is parsed by some UNIX tools...
+ */
+static void
+kernconfdump(const char *file)
+{
+ struct stat st;
+ FILE *fp, *pp;
+ int error, len, osz, r;
+ unsigned int off, size;
+ char *cmd, *o;
+
+ r = open(file, O_RDONLY);
+ if (r == -1)
+ errx(EXIT_FAILURE, "Couldn't open file '%s'", file);
+ error = fstat(r, &st);
+ if (error == -1)
+ errx(EXIT_FAILURE, "fstat() failed");
+ if (S_ISDIR(st.st_mode))
+ errx(EXIT_FAILURE, "'%s' is a directory", file);
+ fp = fdopen(r, "r");
+ if (fp == NULL)
+ errx(EXIT_FAILURE, "fdopen() failed");
+ osz = 1024;
+ o = calloc(1, osz);
+ if (o == NULL)
+ errx(EXIT_FAILURE, "Couldn't allocate memory");
+ /* ELF note section header. */
+ asprintf(&cmd, "/usr/bin/elfdump -c %s | grep -A 5 kern_conf"
+ "| tail -2 | cut -d ' ' -f 2 | paste - - -", file);
+ if (cmd == NULL)
+ errx(EXIT_FAILURE, "asprintf() failed");
+ pp = popen(cmd, "r");
+ if (pp == NULL)
+ errx(EXIT_FAILURE, "popen() failed");
+ free(cmd);
+ len = fread(o, osz, 1, pp);
+ pclose(pp);
+ r = sscanf(o, "%d\t%d", &off, &size);
+ free(o);
+ if (r != 2)
+ errx(EXIT_FAILURE, "File %s doesn't contain configuration "
+ "file. Either unsupported, or not compiled with "
+ "INCLUDE_CONFIG_FILE", file);
+ r = fseek(fp, off, SEEK_CUR);
+ if (r != 0)
+ errx(EXIT_FAILURE, "fseek() failed");
+ while ((r = fgetc(fp)) != EOF && size-- > 0)
+ fputc(r, stdout);
+ fclose(fp);
+}
OpenPOWER on IntegriCloud