Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 2 Jul 2018 13:08:27 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r335863 - stable/11/usr.sbin/config
Message-ID:  <201807021308.w62D8RfE011662@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Mon Jul  2 13:08:27 2018
New Revision: 335863
URL: https://svnweb.freebsd.org/changeset/base/335863

Log:
  MFC r335642, r335651: config(8) envvar support
  
  r335642:
  config(8): Add `envvar` support
  
  envvar allows adding individual environment variables to the kernel's static
  environment without the overhead of pulling in a full file. envvar in a
  config looks like:
  
  envvar some_var=5
  
  All envvar-provided variables will be added after the env file is processed,
  so envvar keys that exist in the previous env will be overwritten by
  whatever value is set here in the kernel configuration directly.
  
  As an aside, envvar lines are intentionally tokenized differently from
  basically every other line. We used a named state when ENVVAR is encountered
  to gobble up the rest of the line, which will later be cleaned and validated
  in post-processing by sanitize_envline. This turns out to be the simplest
  and cleanest way to allow the flexibility that kenv does while not
  compromising on silly hacks.
  
  r335651:
  config(8): Set envmode if we accept an envvar

Modified:
  stable/11/usr.sbin/config/config.5
  stable/11/usr.sbin/config/config.h
  stable/11/usr.sbin/config/config.y
  stable/11/usr.sbin/config/lang.l
  stable/11/usr.sbin/config/main.c
  stable/11/usr.sbin/config/mkmakefile.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/usr.sbin/config/config.5
==============================================================================
--- stable/11/usr.sbin/config/config.5	Mon Jul  2 11:02:27 2018	(r335862)
+++ stable/11/usr.sbin/config/config.5	Mon Jul  2 13:08:27 2018	(r335863)
@@ -23,7 +23,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd February 21, 2016
+.Dd June 22, 2018
 .Dt CONFIG 5
 .Os
 .Sh NAME
@@ -124,6 +124,20 @@ the compiled-in environment instead, unless the boot e
 This directive is useful for setting kernel tunables in
 embedded environments that do not start from
 .Xr loader 8 .
+.\" -------- ENVVAR --------
+.Pp
+.It Ic envvar Ar setting
+Specifies an individual environment setting to be added to the kernel's
+compiled-in environment.
+.Ar setting
+must be of the form
+.Dq Va name=value .
+Optional quotes are supported in both name and value.
+All environment variables specified with
+.Ic envvar
+will be set after any
+.Ic env
+files are included.
 .\" -------- FILES --------
 .Pp
 .It Ic files Ar filename

Modified: stable/11/usr.sbin/config/config.h
==============================================================================
--- stable/11/usr.sbin/config/config.h	Mon Jul  2 11:02:27 2018	(r335862)
+++ stable/11/usr.sbin/config/config.h	Mon Jul  2 13:08:27 2018	(r335863)
@@ -137,6 +137,13 @@ struct opt_list {
 
 SLIST_HEAD(, opt_list) otab;
 
+struct envvar {
+	char	*env_str;
+	STAILQ_ENTRY(envvar) envvar_next;
+};
+
+STAILQ_HEAD(envvar_head, envvar) envvars;
+
 struct hint {
 	char	*hint_name;
 	STAILQ_ENTRY(hint) hint_next;

Modified: stable/11/usr.sbin/config/config.y
==============================================================================
--- stable/11/usr.sbin/config/config.y	Mon Jul  2 11:02:27 2018	(r335862)
+++ stable/11/usr.sbin/config/config.y	Mon Jul  2 13:08:27 2018	(r335863)
@@ -12,6 +12,7 @@
 %token	DEVICE
 %token	NODEVICE
 %token	ENV
+%token	ENVVAR
 %token	EQUALS
 %token	PLUSEQUALS
 %token	HINTS
@@ -26,6 +27,7 @@
 %token	INCLUDE
 %token	FILES
 
+%token	<str>	ENVLINE
 %token	<str>	ID
 %token	<val>	NUMBER
 
@@ -191,6 +193,16 @@ Config_spec:
 		env = $2;
 		envmode = 1;
 		} |
+	ENVVAR ENVLINE {
+		struct envvar *envvar;
+
+		envvar = (struct envvar *)calloc(1, sizeof (struct envvar));
+		if (envvar == NULL)
+			err(EXIT_FAILURE, "calloc");
+		envvar->env_str = $2;
+		STAILQ_INSERT_TAIL(&envvars, envvar, envvar_next);
+		envmode = 1;
+	        } |
 	HINTS ID {
 		struct hint *hint;
 

Modified: stable/11/usr.sbin/config/lang.l
==============================================================================
--- stable/11/usr.sbin/config/lang.l	Mon Jul  2 11:02:27 2018	(r335862)
+++ stable/11/usr.sbin/config/lang.l	Mon Jul  2 13:08:27 2018	(r335863)
@@ -68,6 +68,7 @@ struct kt {
 	{ "nodevice",	NODEVICE },
 	{ "nodevices",	NODEVICE },
 	{ "env",	ENV },
+	{ "envvar",	ENVVAR },
 	{ "hints",	HINTS },
 	{ "ident",	IDENT },
 	{ "machine",	ARCH }, /* MACHINE is defined in /sys/param.h */
@@ -103,7 +104,13 @@ int yyerror(const char *);
 ID	[A-Za-z_][-A-Za-z_0-9]*
 PATH	[./][-/.%^A-Za-z_0-9]+
 %START TOEOL
+%START ENVC
 %%
+<ENVC>[^#\n]*	{
+			BEGIN 0;
+			yylval.str = strdup(yytext);
+			return ENVLINE;
+		}
 {ID}		{
 			int i;
 
@@ -113,6 +120,9 @@ PATH	[./][-/.%^A-Za-z_0-9]+
 				yylval.str = strdup(yytext);
 				return ID;
 			}
+			/* We'll glom onto the rest of an envvar line */
+			if (i == ENVVAR)
+				BEGIN ENVC;
 			return i;
 		}
 \\\"[^"]+\\\"	{

Modified: stable/11/usr.sbin/config/main.c
==============================================================================
--- stable/11/usr.sbin/config/main.c	Mon Jul  2 11:02:27 2018	(r335862)
+++ stable/11/usr.sbin/config/main.c	Mon Jul  2 13:08:27 2018	(r335863)
@@ -202,6 +202,7 @@ main(int argc, char **argv)
 	STAILQ_INIT(&fntab);
 	STAILQ_INIT(&ftab);
 	STAILQ_INIT(&hints);
+	STAILQ_INIT(&envvars);
 	if (yyparse())
 		exit(3);
 

Modified: stable/11/usr.sbin/config/mkmakefile.c
==============================================================================
--- stable/11/usr.sbin/config/mkmakefile.c	Mon Jul  2 11:02:27 2018	(r335862)
+++ stable/11/usr.sbin/config/mkmakefile.c	Mon Jul  2 13:08:27 2018	(r335863)
@@ -44,6 +44,7 @@ static const char rcsid[] =
 #include <ctype.h>
 #include <err.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/param.h>
@@ -236,6 +237,63 @@ makehints(void)
 	moveifchanged(path("hints.c.new"), path("hints.c"));
 }
 
+static void
+sanitize_envline(char *result, const char *src)
+{
+	const char *eq;
+	char c, *dst;
+	bool leading;
+
+	/* If there is no '=' it's not a well-formed name=value line. */
+	if ((eq = strchr(src, '=')) == NULL) {
+		*result = 0;
+		return;
+	}
+	dst = result;
+
+	/* Copy chars before the '=', skipping any leading spaces/quotes. */
+	leading = true;
+	while (src < eq) {
+		c = *src++;
+		if (leading && (isspace(c) || c == '"'))
+			continue;
+		*dst++ = c;
+		leading = false;
+	}
+
+	/* If it was all leading space, we don't have a well-formed line. */
+	if (leading) {
+		*result = 0;
+		return;
+	}
+
+	/* Trim spaces/quotes immediately before the '=', then copy the '='. */
+	while (isspace(dst[-1]) || dst[-1] == '"')
+		--dst;
+	*dst++ = *src++;
+
+	/* Copy chars after the '=', skipping any leading whitespace. */
+	leading = true;
+	while ((c = *src++) != 0) {
+		if (leading && (isspace(c) || c == '"'))
+			continue;
+		*dst++ = c;
+		leading = false;
+	}
+
+	/* If it was all leading space, it's a valid 'var=' (nil value). */
+	if (leading) {
+		*dst = 0;
+		return;
+	}
+
+	/* Trim trailing whitespace and quotes. */
+	while (isspace(dst[-1]) || dst[-1] == '"')
+		--dst;
+
+	*dst = 0;
+}
+
 /*
  * Build env.c from the skeleton
  */
@@ -243,8 +301,8 @@ void
 makeenv(void)
 {
 	FILE *ifp, *ofp;
-	char line[BUFSIZ];
-	char *s;
+	char line[BUFSIZ], result[BUFSIZ], *linep;
+	struct envvar *envvar;
 
 	if (env) {
 		ifp = fopen(env, "r");
@@ -263,34 +321,19 @@ makeenv(void)
 	fprintf(ofp, "char static_env[] = {\n");
 	if (ifp) {
 		while (fgets(line, BUFSIZ, ifp) != NULL) {
-			/* zap trailing CR and/or LF */
-			while ((s = strrchr(line, '\n')) != NULL)
-				*s = '\0';
-			while ((s = strrchr(line, '\r')) != NULL)
-				*s = '\0';
-			/* remove # comments */
-			s = strchr(line, '#');
-			if (s)
-				*s = '\0';
-			/* remove any whitespace and " characters */
-			s = line;
-			while (*s) {
-				if (*s == ' ' || *s == '\t' || *s == '"') {
-					while (*s) {
-						s[0] = s[1];
-						s++;
-					}
-					/* start over */
-					s = line;
-					continue;
-				}
-				s++;
-			}
+			sanitize_envline(result, line);
 			/* anything left? */
-			if (*line == '\0')
+			if (*result == '\0')
 				continue;
-			fprintf(ofp, "\"%s\\0\"\n", line);
+			fprintf(ofp, "\"%s\\0\"\n", result);
 		}
+	}
+	STAILQ_FOREACH(envvar, &envvars, envvar_next) {
+		linep = envvar->env_str;
+		sanitize_envline(result, linep);
+		if (*result == '\0')
+			continue;
+		fprintf(ofp, "\"%s\\0\"\n", result);
 	}
 	fprintf(ofp, "\"\\0\"\n};\n");
 	if (ifp)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201807021308.w62D8RfE011662>