Author: mhorne
Date: Mon Sep 21 15:24:44 2020
New Revision: 365945
URL: https://svnweb.freebsd.org/changeset/base/365945

Log:
  Add getenv(9) boolean parsing functions
  
  This adds the getenv_bool() function, to parse a boolean value from a
  kernel environment variable or tunable. This works for traditional
  boolean values like "0" and "1", and also "true" and "false"
  (case-insensitive). These semantics do not yet apply to sysctls declared
  using SYSCTL_BOOL with CTLFLAG_TUN (they still only parse 1 and 0).
  
  Also added are two wrapper functions, getenv_is_true() and
  getenv_is_false(). These are slightly simpler for callers wishing to
  perform a single check of a configuration variable.
  
  Reviewed by:  jhb (slightly earlier version)
  Sponsored by: NetApp, Inc.
  Sponsored by: Klara, Inc.
  Differential Revision:        https://reviews.freebsd.org/D26270

Modified:
  head/share/man/man9/Makefile
  head/share/man/man9/getenv.9
  head/sys/kern/kern_environment.c
  head/sys/sys/kernel.h
  head/sys/sys/systm.h

Modified: head/share/man/man9/Makefile
==============================================================================
--- head/share/man/man9/Makefile        Mon Sep 21 12:37:41 2020        
(r365944)
+++ head/share/man/man9/Makefile        Mon Sep 21 15:24:44 2020        
(r365945)
@@ -1092,6 +1092,9 @@ MLINKS+=getenv.9 freeenv.9 \
        getenv.9 getenv_quad.9 \
        getenv.9 getenv_uint.9 \
        getenv.9 getenv_ulong.9 \
+       getenv.9 getenv_bool.9 \
+       getenv.9 getenv_is_true.9 \
+       getenv.9 getenv_is_false.9 \
        getenv.9 kern_getenv.9 \
        getenv.9 kern_setenv.9 \
        getenv.9 kern_unsetenv.9 \

Modified: head/share/man/man9/getenv.9
==============================================================================
--- head/share/man/man9/getenv.9        Mon Sep 21 12:37:41 2020        
(r365944)
+++ head/share/man/man9/getenv.9        Mon Sep 21 15:24:44 2020        
(r365945)
@@ -27,7 +27,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd June 1, 2017
+.Dd September 21, 2020
 .Dt GETENV 9
 .Os
 .Sh NAME
@@ -39,6 +39,9 @@
 .Nm getenv_quad ,
 .Nm getenv_uint ,
 .Nm getenv_ulong ,
+.Nm getenv_bool ,
+.Nm getenv_is_true ,
+.Nm getenv_is_false ,
 .Nm kern_setenv ,
 .Nm testenv ,
 .Nm kern_unsetenv
@@ -63,6 +66,12 @@
 .Ft int
 .Fn getenv_ulong "const char *name" "unsigned long *data"
 .Ft int
+.Fn getenv_bool "const char *name" "bool *data"
+.Ft bool
+.Fn getenv_is_true "const char *name"
+.Ft bool
+.Fn getenv_is_false "const char *name"
+.Ft int
 .Fn kern_setenv "const char *name" "const char *value"
 .Ft int
 .Fn testenv "const char *name"
@@ -194,6 +203,28 @@ up to
 characters of its value are copied to the buffer pointed to by
 .Fa data
 followed by a null character and a non-zero value is returned.
+.Pp
+The
+.Fn getenv_bool
+function interprets the value of the kernel environment variable
+.Fa name
+as a boolean value by performing a case-insensitive comparison against the
+strings "1",
+"0",
+"true",
+and "false".
+If the environment variable exists and has a valid boolean value, then that
+value will be copied to the variable pointed to by
+.Fa data .
+If the environment variable exists but is not a boolean value, then a warning
+will be printed to the kernel message buffer.
+The
+.Fn getenv_is_true
+and
+.Fn getenv_is_false
+functions are wrappers around
+.Fn getenv_bool
+that simplify testing for a desired boolean value.
 .Sh RETURN VALUES
 The
 .Fn kern_getenv
@@ -211,12 +242,25 @@ The
 .Fn testenv
 function returns zero if the specified environment variable does not exist and
 a non-zero value if it does exist.
+.Pp
 The
 .Fn getenv_int ,
 .Fn getenv_long ,
 .Fn getenv_string ,
 .Fn getenv_quad ,
 .Fn getenv_uint ,
+.Fn getenv_ulong ,
 and
-.Fn getenv_ulong
+.Fn getenv_bool
 functions return a non-zero value on success and zero on failure.
+.Pp
+The
+.Fn getenv_is_true
+and
+.Fn getenv_is_false
+functions return
+.Dv true
+if the specified environment variable exists and its value matches the desired
+boolean condition, and
+.Dv false
+otherwise.

Modified: head/sys/kern/kern_environment.c
==============================================================================
--- head/sys/kern/kern_environment.c    Mon Sep 21 12:37:41 2020        
(r365944)
+++ head/sys/kern/kern_environment.c    Mon Sep 21 15:24:44 2020        
(r365945)
@@ -942,6 +942,65 @@ error:
 }
 
 /*
+ * Return a boolean value from an environment variable. This can be in
+ * numerical or string form, i.e. "1" or "true".
+ */
+int
+getenv_bool(const char *name, bool *data)
+{
+       char *val;
+       int ret = 0;
+
+       if (name == NULL)
+               return (0);
+
+       val = kern_getenv(name);
+       if (val == NULL)
+               return (0);
+
+       if ((strcmp(val, "1") == 0) || (strcasecmp(val, "true") == 0)) {
+               *data = true;
+               ret = 1;
+       } else if ((strcmp(val, "0") == 0) || (strcasecmp(val, "false") == 0)) {
+               *data = false;
+               ret = 1;
+       } else {
+               /* Spit out a warning for malformed boolean variables. */
+               printf("Environment variable %s has non-boolean value \"%s\"\n",
+                   name, val);
+       }
+       freeenv(val);
+
+       return (ret);
+}
+
+/*
+ * Wrapper around getenv_bool to easily check for true.
+ */
+bool
+getenv_is_true(const char *name)
+{
+       bool val;
+
+       if (getenv_bool(name, &val) != 0)
+               return (val);
+       return (false);
+}
+
+/*
+ * Wrapper around getenv_bool to easily check for false.
+ */
+bool
+getenv_is_false(const char *name)
+{
+       bool val;
+
+       if (getenv_bool(name, &val) != 0)
+               return (!val);
+       return (false);
+}
+
+/*
  * Find the next entry after the one which (cp) falls within, return a
  * pointer to its start or NULL if there are no more.
  */
@@ -1005,6 +1064,14 @@ tunable_quad_init(void *data)
        struct tunable_quad *d = (struct tunable_quad *)data;
 
        TUNABLE_QUAD_FETCH(d->path, d->var);
+}
+
+void
+tunable_bool_init(void *data)
+{
+       struct tunable_bool *d = (struct tunable_bool *)data;
+
+       TUNABLE_BOOL_FETCH(d->path, d->var);
 }
 
 void

Modified: head/sys/sys/kernel.h
==============================================================================
--- head/sys/sys/kernel.h       Mon Sep 21 12:37:41 2020        (r365944)
+++ head/sys/sys/kernel.h       Mon Sep 21 15:24:44 2020        (r365945)
@@ -421,6 +421,25 @@ struct tunable_quad {
 
 #define        TUNABLE_QUAD_FETCH(path, var)   getenv_quad((path), (var))
 
+/*
+ * bool
+ */
+extern void tunable_bool_init(void *);
+struct tunable_bool {
+       const char *path;
+       bool *var;
+};
+#define        TUNABLE_BOOL(path, var) \
+       static struct tunable_bool __CONCAT(__tunable_bool_, __LINE__) = { \
+               (path),                                         \
+               (var),                                          \
+       };                                                      \
+       SYSINIT(__CONCAT(__Tunable_init_, __LINE__),            \
+           SI_SUB_TUNABLES, SI_ORDER_MIDDLE, tunable_bool_init, \
+           &__CONCAT(__tunable_bool_, __LINE__))
+
+#define        TUNABLE_BOOL_FETCH(path, var)   getenv_bool((path), (var))
+
 extern void tunable_str_init(void *);
 struct tunable_str {
        const char *path;

Modified: head/sys/sys/systm.h
==============================================================================
--- head/sys/sys/systm.h        Mon Sep 21 12:37:41 2020        (r365944)
+++ head/sys/sys/systm.h        Mon Sep 21 15:24:44 2020        (r365945)
@@ -461,6 +461,9 @@ int getenv_string(const char *name, char *data, int si
 int    getenv_int64(const char *name, int64_t *data);
 int    getenv_uint64(const char *name, uint64_t *data);
 int    getenv_quad(const char *name, quad_t *data);
+int    getenv_bool(const char *name, bool *data);
+bool   getenv_is_true(const char *name);
+bool   getenv_is_false(const char *name);
 int    kern_setenv(const char *name, const char *value);
 int    kern_unsetenv(const char *name);
 int    testenv(const char *name);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to