diff -Nur src.o/usr.sbin/config/Makefile src/usr.sbin/config/Makefile --- src.o/usr.sbin/config/Makefile Fri Dec 9 07:46:40 2005 +++ src/usr.sbin/config/Makefile Mon Apr 30 03:39:19 2007 @@ -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 -Nur src.o/usr.sbin/config/config.8 src/usr.sbin/config/config.8 --- src.o/usr.sbin/config/config.8 Sat Oct 21 22:09:51 2006 +++ src/usr.sbin/config/config.8 Mon Apr 30 06:07:44 2007 @@ -28,7 +28,7 @@ .\" @(#)config.8 8.2 (Berkeley) 4/19/94 .\" $FreeBSD: src/usr.sbin/config/config.8,v 1.45 2006/10/21 20:09:51 ru Exp $ .\" -.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 @@ 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 @@ 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 @@ 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 @@ .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 -Nur src.o/usr.sbin/config/config.h src/usr.sbin/config/config.h --- src.o/usr.sbin/config/config.h Tue Oct 24 02:31:59 2006 +++ src/usr.sbin/config/config.h Wed Mar 21 07:17:57 2007 @@ -38,6 +38,12 @@ #include #include +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 @@ 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 @@ 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 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 -Nur src.o/usr.sbin/config/config.y src/usr.sbin/config/config.y --- src.o/usr.sbin/config/config.y Tue Oct 24 02:31:59 2006 +++ src/usr.sbin/config/config.y Wed Mar 21 07:17:57 2007 @@ -70,6 +70,7 @@ * $FreeBSD: src/usr.sbin/config/config.y,v 1.76 2006/10/24 00:31:59 imp Exp $ */ +#include #include #include #include @@ -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 @@ 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 @@ Config_spec SEMICOLON | INCLUDE ID SEMICOLON - = { include($2, 0); }; + = { + if (incignore == 0) + include($2, 0); + }; | FILES ID SEMICOLON = { newfile($2); }; @@ -170,11 +177,11 @@ 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 @@ = { 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 @@ 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 @@ * 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 @@ { struct device *np; - if (finddev(name)) { + if (finddev(&dtab, name)) { printf("WARNING: duplicate device `%s' encountered.\n", name); return; } @@ -375,17 +384,36 @@ } /* - * 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 @@ { 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 @@ * 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 -Nur src.o/usr.sbin/config/kernconf.tmpl src/usr.sbin/config/kernconf.tmpl --- src.o/usr.sbin/config/kernconf.tmpl Thu Jan 1 01:00:00 1970 +++ src/usr.sbin/config/kernconf.tmpl Thu Mar 8 12:16:49 2007 @@ -0,0 +1,11 @@ +#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 -Nur src.o/usr.sbin/config/lang.l src/usr.sbin/config/lang.l --- src.o/usr.sbin/config/lang.l Sat Dec 3 21:04:24 2005 +++ src/usr.sbin/config/lang.l Mon Apr 30 07:54:55 2007 @@ -207,6 +207,30 @@ 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 @@ 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 @@ 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 -Nur src.o/usr.sbin/config/main.c src/usr.sbin/config/main.c --- src.o/usr.sbin/config/main.c Tue Oct 24 02:31:59 2006 +++ src/usr.sbin/config/main.c Mon Apr 30 06:07:44 2007 @@ -43,9 +43,12 @@ #include #include +#include #include #include #include + +#include #include #include #include @@ -73,11 +76,19 @@ 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 @@ 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 @@ case 'p': profiling++; break; + case 'V': + printf("%d\n", CONFIGVERS); + exit(0); + case 'x': + kernfile = optarg; + break; case '?': default: usage(); @@ -122,23 +140,23 @@ 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 @@ } 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 @@ (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 @@ 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 @@ 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(); } /* @@ -523,4 +626,58 @@ hl->h_name = s; 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); } --- src.o/sys/kern/kern_mib.c Sat Apr 7 19:30:44 2007 +++ src/sys/kern/kern_mib.c Mon Apr 30 01:20:31 2007 @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -294,6 +295,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,