aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMattias Andrée <m@maandree.se>2025-01-30 18:42:27 +0100
committerMattias Andrée <m@maandree.se>2025-01-30 18:42:27 +0100
commitaebf2524909f0c0e3aec7f78fa01ad908f7da3a0 (patch)
tree86881e1b1b299990e6726eda5dde3f1f77c4f180
downloadlibenv-aebf2524909f0c0e3aec7f78fa01ad908f7da3a0.tar.gz
libenv-aebf2524909f0c0e3aec7f78fa01ad908f7da3a0.tar.bz2
libenv-aebf2524909f0c0e3aec7f78fa01ad908f7da3a0.tar.xz
First commit
Signed-off-by: Mattias Andrée <m@maandree.se>
-rw-r--r--.gitignore14
-rw-r--r--LICENSE15
-rw-r--r--Makefile116
-rw-r--r--README25
-rw-r--r--common.h30
-rw-r--r--config.mk8
-rw-r--r--enum_libenv_class.3197
-rw-r--r--libenv.733
-rw-r--r--libenv.h563
l---------libenv_class.31
-rw-r--r--libenv_filter_name_list.382
-rw-r--r--libenv_filter_name_list.c15
l---------libenv_filter_name_list_with_dealloc.31
-rw-r--r--libenv_filter_name_list_with_dealloc.c15
-rw-r--r--libenv_filter_variable_list.384
-rw-r--r--libenv_filter_variable_list.c15
l---------libenv_filter_variable_list_with_dealloc.31
-rw-r--r--libenv_filter_variable_list_with_dealloc.c15
-rw-r--r--libenv_get_chosen_list.369
-rw-r--r--libenv_get_chosen_list.c15
-rw-r--r--libenv_get_complete_list.382
-rw-r--r--libenv_get_complete_list.c211
-rw-r--r--libenv_select_name_list.382
-rw-r--r--libenv_select_name_list.c15
l---------libenv_select_name_list_with_dealloc.31
-rw-r--r--libenv_select_name_list_with_dealloc.c15
-rw-r--r--libenv_select_variable_list.384
-rw-r--r--libenv_select_variable_list.c15
l---------libenv_select_variable_list_with_dealloc.31
-rw-r--r--libenv_select_variable_list_with_dealloc.c15
l---------libenv_variable.31
l---------libenv_vfilter_name_list.31
-rw-r--r--libenv_vfilter_name_list.c12
l---------libenv_vfilter_name_list_with_dealloc.31
-rw-r--r--libenv_vfilter_name_list_with_dealloc.c12
l---------libenv_vfilter_variable_list.31
-rw-r--r--libenv_vfilter_variable_list.c12
l---------libenv_vfilter_variable_list_with_dealloc.31
-rw-r--r--libenv_vfilter_variable_list_with_dealloc.c12
l---------libenv_vget_chosen_list.31
-rw-r--r--libenv_vget_chosen_list.c23
-rw-r--r--libenv_vprocess_list__.c64
l---------libenv_vselect_name_list.31
-rw-r--r--libenv_vselect_name_list.c12
l---------libenv_vselect_name_list_with_dealloc.31
-rw-r--r--libenv_vselect_name_list_with_dealloc.c12
l---------libenv_vselect_variable_list.31
-rw-r--r--libenv_vselect_variable_list.c12
l---------libenv_vselect_variable_list_with_dealloc.31
-rw-r--r--libenv_vselect_variable_list_with_dealloc.c12
-rw-r--r--mk/linux.mk6
-rw-r--r--mk/macos.mk6
-rw-r--r--mk/windows.mk6
l---------struct_libenv_variable.31
54 files changed, 2047 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a071ed4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+*\#*
+*~
+*.o
+*.a
+*.lo
+*.su
+*.so
+*.so.*
+*.dll
+*.dylib
+*.gch
+*.gcov
+*.gcno
+*.gcda
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..0e6be1c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+© 2025 Mattias Andrée <m@maandree.se>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..18d3ff1
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,116 @@
+.POSIX:
+
+CONFIGFILE = config.mk
+include $(CONFIGFILE)
+
+OS = linux
+# Linux: linux
+# Mac OS: macos
+# Windows: windows
+include mk/$(OS).mk
+
+
+LIB_MAJOR = 1
+LIB_MINOR = 0
+LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR)
+LIB_NAME = env
+
+
+OBJ =\
+ libenv_get_complete_list.o\
+ $(OBJ_TESTABLE)
+
+OBJ_TESTABLE_PUBLIC =\
+ libenv_vget_chosen_list.o\
+ libenv_get_chosen_list.o\
+ libenv_vfilter_name_list.o\
+ libenv_filter_name_list.o\
+ libenv_vfilter_variable_list.o\
+ libenv_filter_variable_list.o\
+ libenv_vselect_name_list.o\
+ libenv_select_name_list.o\
+ libenv_vselect_variable_list.o\
+ libenv_select_variable_list.o\
+ libenv_vfilter_name_list_with_dealloc.o\
+ libenv_filter_name_list_with_dealloc.o\
+ libenv_vfilter_variable_list_with_dealloc.o\
+ libenv_filter_variable_list_with_dealloc.o\
+ libenv_vselect_name_list_with_dealloc.o\
+ libenv_select_name_list_with_dealloc.o\
+ libenv_vselect_variable_list_with_dealloc.o\
+ libenv_select_variable_list_with_dealloc.o\
+
+OBJ_TESTABLE =\
+ $(OBJ_TESTABLE_PUBLIC)\
+ libenv_vprocess_list__.o
+
+OBJ_PUBLIC =\
+ libenv_get_complete_list.o\
+ $(OBJ_TESTABLE_PUBLIC)
+
+HDR =\
+ libenv.h\
+ common.h
+
+MAN3 =\
+ $(OBJ_PUBLIC:.o=.3)\
+ enum_libenv_class.3\
+ libenv_class.3\
+ struct_libenv_variable.3\
+ libenv_variable.3
+
+MAN7 =\
+ libenv.7
+
+LOBJ = $(OBJ:.o=.lo)
+
+
+all: libenv.a libenv.$(LIBEXT)
+$(OBJ): $(HDR)
+$(LOBJ): $(HDR)
+
+.c.o:
+ $(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS)
+
+.c.lo:
+ $(CC) -fPIC -c -o $@ $< $(CFLAGS) $(CPPFLAGS)
+
+libenv.a: $(OBJ)
+ @rm -f -- $@
+ $(AR) rc $@ $(OBJ)
+ $(AR) ts $@ > /dev/null
+
+libenv.$(LIBEXT): $(LOBJ)
+ $(CC) $(LIBFLAGS) -o $@ $(LOBJ) $(LDFLAGS)
+
+install: libenv.a libenv.$(LIBEXT)
+ mkdir -p -- "$(DESTDIR)$(PREFIX)/lib"
+ mkdir -p -- "$(DESTDIR)$(PREFIX)/include"
+ mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man3"
+ mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man7"
+ cp -- libenv.a "$(DESTDIR)$(PREFIX)/lib/"
+ cp -- libenv.$(LIBEXT) "$(DESTDIR)$(PREFIX)/lib/libenv.$(LIBMINOREXT)"
+ $(FIX_INSTALL_NAME) "$(DESTDIR)$(PREFIX)/lib/libenv.$(LIBMINOREXT)"
+ ln -sf -- libenv.$(LIBMINOREXT) "$(DESTDIR)$(PREFIX)/lib/libenv.$(LIBMAJOREXT)"
+ ln -sf -- libenv.$(LIBMAJOREXT) "$(DESTDIR)$(PREFIX)/lib/libenv.$(LIBEXT)"
+ cp -- libenv.h "$(DESTDIR)$(PREFIX)/include/"
+ cp -P -- $(MAN3) "$(DESTDIR)$(MANPREFIX)/man3/"
+ cp -P -- $(MAN7) "$(DESTDIR)$(MANPREFIX)/man7/"
+
+uninstall:
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libenv.a"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libenv.$(LIBMAJOREXT)"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libenv.$(LIBMINOREXT)"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libenv.$(LIBEXT)"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/include/libenv.h"
+ -cd -- "$(DESTDIR)$(MANPREFIX)/man3/" && rm -f -- $(MAN3)
+ -cd -- "$(DESTDIR)$(MANPREFIX)/man7/" && rm -f -- $(MAN7)
+
+clean:
+ -rm -f -- *.o *.a *.lo *.su *.so *.so.* *.dll *.dylib
+ -rm -f -- *.gch *.gcov *.gcno *.gcda *.$(LIBEXT)
+
+.SUFFIXES:
+.SUFFIXES: .lo .o .c
+
+.PHONY: all install uninstall clean
diff --git a/README b/README
new file mode 100644
index 0000000..109984f
--- /dev/null
+++ b/README
@@ -0,0 +1,25 @@
+NAME
+ libenv - Environment sanitation library
+
+SYNOPSIS
+ #include <libenv.h>
+
+ Link with -lenv.
+
+DESCRIPTION
+ The libenv software library is C library designed to help
+ utilities perform sanitation of environment variables.
+
+ Some utilities need to remove environment variables that are
+ not appropriate for the new context that the utility entires.
+ Likewise some utilities may meed to remove all except some
+ special environment variables. libenv provides a database of
+ environment variable variables that could be interesting and
+ provides functionality to describe the new context the is is
+ entered and filter out environment variables accordingly.
+
+SEE ALSO
+ libenv_filter_variable_list(3),
+ libenv_select_variable_list(3),
+ libenv_get_chosen_list(3),
+ libenv_get_complete_list(3)
diff --git a/common.h b/common.h
new file mode 100644
index 0000000..02af2a1
--- /dev/null
+++ b/common.h
@@ -0,0 +1,30 @@
+/* See LICENSE file for copyright and license details. */
+#include "libenv.h"
+#include <stdlib.h>
+
+
+#define HAVE_HEAD 1
+#define NO_HEAD 0
+
+#define NAMES 1
+#define VARIABLES 0
+
+#define FILTER 1, 1
+#define SELECT 0, 0
+
+
+size_t libenv_vprocess_list__(void *, enum libenv_class, va_list, int have_head, int names, int filter, int all, int dealloc);
+
+static inline size_t
+libenv_vprocess_list_without_dealloc__(const char **variables, enum libenv_class classes_head, va_list classes_tail,
+ int have_head, int names, int filter, int all)
+{
+ return libenv_vprocess_list__(variables, classes_head, classes_tail, have_head, names, filter, all, 0);
+}
+
+static inline size_t
+libenv_vprocess_list_with_dealloc__(char **variables, enum libenv_class classes_head, va_list classes_tail,
+ int have_head, int names, int filter, int all)
+{
+ return libenv_vprocess_list__(variables, classes_head, classes_tail, have_head, names, filter, all, 1);
+}
diff --git a/config.mk b/config.mk
new file mode 100644
index 0000000..f4adf12
--- /dev/null
+++ b/config.mk
@@ -0,0 +1,8 @@
+PREFIX = /usr
+MANPREFIX = $(PREFIX)/share/man
+
+CC = c99
+
+CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE
+CFLAGS =
+LDFLAGS =
diff --git a/enum_libenv_class.3 b/enum_libenv_class.3
new file mode 100644
index 0000000..25edd60
--- /dev/null
+++ b/enum_libenv_class.3
@@ -0,0 +1,197 @@
+.TH ENUM_LIBENV_CLASS 3 libenv
+.SH NAME
+enum libenv_class - Environment variables classes
+
+.SH SYNOPSIS
+.nf
+#include <libenv.h>
+
+enum libenv_class {
+ LIBENV_END = 0,
+ /* ... members omitted, see listing below ... */
+};
+.fi
+
+.SH DESCRIPTION
+The
+.B enum libenv_class
+contains one dummy value,
+.IR LIBENV_END ,
+used to mark the end of a class list for variadic functions.
+In addition to this dummy value, it also contains the following
+values used to describe a class of environment variables:
+.TP
+.B LIBENV_DISPLAY
+Environment variables necessary for the
+graphical environment.
+.TP
+.B LIBENV_DISPLAY_CONFIG
+Environment variables that configure
+the graphical environment.
+.TP
+.B LIBENV_DESKTOP
+Environment variables that describe
+the desktop environment.
+.TP
+.B LIBENV_TERMINAL_CAPS
+Environment variables that describe
+the terminals capabilities.
+.TP
+.B LIBENV_LOCAL_TERMINAL
+Environment variables that describe
+the terminals but is only meaningful
+for the local host.
+.TP
+.B LIBENV_LOCALE
+Environment variables that configure
+the locale.
+.TP
+.B LIBENV_TIMEZONE
+Environment variables that configure
+the timezone.
+.TP
+.B LIBENV_SESSION
+Environment variables that describe
+the current session.
+
+This for example includes variables
+added by
+.BR sshd (8)
+to describe the remote connection.
+
+This does not include display, desktop,
+or terminal information, nor does
+include information to identify the
+user.
+.TP
+.B LIBENV_THEME_CONFIG
+Environment variables that configure
+the user's theme.
+
+This is excludes variables listed for
+.I LIBENV_THEME_PLUGIN
+except in the
+hypothetical scenario where it names
+a plugin and additional configurations.
+.TP
+.B LIBENV_THEME_PLUGIN
+Environment variables that describe
+the plugins the user's theme requires.
+.TP
+.B LIBENV_INTERNET
+Environment variables that configures
+the user's internet configurations,
+including mainly proxies.
+.TP
+.B LIBENV_AUDIO
+Environment variables that configures
+the user's audio.
+.TP
+.B LIBENV_USER
+Environment variables that describe
+any information gathered about the
+user from
+.BR passwd (5)
+or login parameters.
+.TP
+.B LIBENV_APPLICATIONS
+Environment variables that default
+applications configured for the user.
+.TP
+.B LIBENV_PREFERENCES
+Environment variables that configure
+preferences, for the user, for various
+applications.
+.TP
+.B LIBENV_SYSTEM_PATHS
+Environment variables that list directories
+configured system wide (but could be
+overwritten for the user).
+
+Environment variables with this classification
+has at least also
+.IR LIBENV_PATH .
+.TP
+.B LIBENV_USER_PATHS
+Environment variables that list directories
+configured for the user.
+
+Environment variables with this classification
+has at least also
+.IR LIBENV_PATH .
+.TP
+.B LIBENV_PWD
+Environment variables that contain
+current and past working directories.
+
+Environment variables with this classification
+has at least also
+.IR LIBENV_PATH .
+.TP
+.B LIBENV_EXEC
+Environment variables that contain
+information about the executed utility.
+.TP
+.B LIBENV_PATH
+Environment variables that contain
+filesystem paths.
+
+Any environment variable with this
+classification has at least one other
+classification.
+.TP
+.B LIBENV_REMOTE_UNSAFE
+Environment variables that should be removed
+when entering a remote session.
+
+Any environment variable with this
+classification has at least one other
+classification.
+.TP
+.B LIBENV_REMOTE_SAFE
+Environment variables that should be can
+safely be kepted when entering a remote
+session.
+
+Any environment variable with this
+classification has at least one other
+classification.
+.TP
+.B LIBENV_LOGIN_UNSAFE
+Environment variables that should be removed
+when entering a logging into a new user.
+
+Any environment variable with this
+classification has at least one other
+classification.
+.TP
+.B LIBENV_LOGIN_SAFE
+Environment variables that should be can
+safely be kepted when entering a logging
+into a new user.
+
+Any environment variable with this
+classification has at least one other
+classification.
+.TP
+.B LIBENV_SU_UNSAFE
+Environment variables that should be removed
+when escalating privileges.
+
+Any environment variable with this
+classification has at least one other
+classification.
+.TP
+.B LIBENV_SU_SAFE
+Environment variables that should be can
+safely be kepted when escalating privileges.
+
+Any environment variable with this
+classification has at least one other
+classification.
+
+.SH SEE ALSO
+.BR libenv (7),
+.BR libenv_get_chosen_list (3),
+.BR libenv_filter_variable_list (3),
+.BR libenv_select_variable_list (3).
diff --git a/libenv.7 b/libenv.7
new file mode 100644
index 0000000..638a47f
--- /dev/null
+++ b/libenv.7
@@ -0,0 +1,33 @@
+.TH LIBENV 7 libenv
+.SH NAME
+libenv - Environment sanitation library
+
+.SH SYNOPSIS
+.nf
+#include <libenv.h>
+.fi
+.PP
+Link with
+.IR -lenv .
+
+.SH DESCRIPTION
+The
+.B libenv
+software library is C library designed to help
+utilities perform sanitation of environment variables.
+.PP
+Some utilities need to remove environment variables that are
+not appropriate for the new context that the utility entires.
+Likewise some utilities may meed to remove all except some
+special environment variables.
+.B libenv
+provides a database of
+environment variable variables that could be interesting and
+provides functionality to describe the new context the is is
+entered and filter out environment variables accordingly.
+
+.SH SEE ALSO
+.BR libenv_filter_variable_list (3),
+.BR libenv_select_variable_list (3),
+.BR libenv_get_chosen_list (3),
+.BR libenv_get_complete_list (3).
diff --git a/libenv.h b/libenv.h
new file mode 100644
index 0000000..a1ac96d
--- /dev/null
+++ b/libenv.h
@@ -0,0 +1,563 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBENV_H
+#define LIBENV_H
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#if defined(__GNUC__)
+# define LIBENV_MALLOC__ __attribute__((__malloc__, __warn_unused_result__))
+# define LIBENV_RET_NONNULL__ __attribute__((__returns_nonnull__, __warn_unused_result__))
+#else
+# define LIBENV_MALLOC__
+# define LIBENV_RET_NONNULL__
+#endif
+
+
+/**
+ * Environment variable class
+ */
+enum libenv_class {
+ /**
+ * Used to mark the end of a class list in
+ * for a variadic function
+ */
+ LIBENV_END = 0,
+
+ /* Classes: */
+
+ /**
+ * Environment variables necessary for the
+ * graphical environment
+ */
+ LIBENV_DISPLAY,
+
+ /**
+ * Environment variables that configure
+ * the graphical environment
+ */
+ LIBENV_DISPLAY_CONFIG,
+
+ /**
+ * Environment variables that describe
+ * the desktop environment
+ */
+ LIBENV_DESKTOP,
+
+ /**
+ * Environment variables that describe
+ * the terminals capabilities
+ */
+ LIBENV_TERMINAL_CAPS,
+
+ /**
+ * Environment variables that describe
+ * the terminals but is only meaningful
+ * for the local host
+ */
+ LIBENV_LOCAL_TERMINAL,
+
+ /**
+ * Environment variables that configure
+ * the locale
+ */
+ LIBENV_LOCALE,
+
+ /**
+ * Environment variables that configure
+ * the timezone
+ */
+ LIBENV_TIMEZONE,
+
+ /**
+ * Environment variables that describe
+ * the current session
+ *
+ * This for example includes variables
+ * added by SSH to describe the remote
+ * connection
+ *
+ * This does not include display, desktop,
+ * or terminal information, nor does
+ * include information to identify the
+ * user
+ */
+ LIBENV_SESSION,
+
+ /**
+ * Environment variables that configure
+ * the user's theme
+ *
+ * This is excludes variables listed
+ * for LIBENV_THEME_PLUGIN except in the
+ * hypothetical scenario where it names
+ * a plugin and additional configurations
+ */
+ LIBENV_THEME_CONFIG,
+
+ /**
+ * Environment variables that describe
+ * the plugins the user's theme requires
+ */
+ LIBENV_THEME_PLUGIN,
+
+ /**
+ * Environment variables that configures
+ * the user's internet configurations,
+ * including mainly proxies
+ */
+ LIBENV_INTERNET,
+
+ /**
+ * Environment variables that configures
+ * the user's audio
+ */
+ LIBENV_AUDIO,
+
+ /**
+ * Environment variables that describe
+ * any information gathered about the
+ * user from passwd(5) or login parameters
+ */
+ LIBENV_USER,
+
+ /**
+ * Environment variables that default
+ * applications configured for the user
+ */
+ LIBENV_APPLICATIONS,
+
+ /**
+ * Environment variables that configure
+ * preferences, for the user, for various
+ * applications
+ */
+ LIBENV_PREFERENCES,
+
+ /**
+ * Environment variables that list directories
+ * configured system wide (but could be
+ * overwritten for the user)
+ *
+ * Environment variables with this classification
+ * has at least also LIBENV_PATH
+ */
+ LIBENV_SYSTEM_PATHS,
+
+ /**
+ * Environment variables that list directories
+ * configured for the user
+ *
+ * Environment variables with this classification
+ * has at least also LIBENV_PATH
+ */
+ LIBENV_USER_PATHS,
+
+ /**
+ * Environment variables that contain
+ * current and past working directories
+ *
+ * Environment variables with this classification
+ * has at least also LIBENV_PATH
+ */
+ LIBENV_PWD,
+
+ /**
+ * Environment variables that contain
+ * information about the executed utility
+ */
+ LIBENV_EXEC,
+
+ /**
+ * Environment variables that contain
+ * filesystem paths
+ *
+ * Any environment variable with this
+ * classification has at least one other
+ * classification
+ */
+ LIBENV_PATH,
+
+ /**
+ * Environment variables that should be removed
+ * when entering a remote session
+ *
+ * Any environment variable with this
+ * classification has at least one other
+ * classification
+ */
+ LIBENV_REMOTE_UNSAFE,
+
+ /**
+ * Environment variables that should be can
+ * safely be kepted when entering a remote
+ * session
+ *
+ * Any environment variable with this
+ * classification has at least one other
+ * classification
+ */
+ LIBENV_REMOTE_SAFE,
+
+ /**
+ * Environment variables that should be removed
+ * when entering a logging into a new user
+ *
+ * Any environment variable with this
+ * classification has at least one other
+ * classification
+ */
+ LIBENV_LOGIN_UNSAFE,
+
+ /**
+ * Environment variables that should be can
+ * safely be kepted when entering a logging
+ * into a new user
+ *
+ * Any environment variable with this
+ * classification has at least one other
+ * classification
+ */
+ LIBENV_LOGIN_SAFE,
+
+ /**
+ * Environment variables that should be removed
+ * when escalating privileges
+ *
+ * Any environment variable with this
+ * classification has at least one other
+ * classification
+ */
+ LIBENV_SU_UNSAFE,
+
+ /**
+ * Environment variables that should be can
+ * safely be kepted when escalating privileges
+ *
+ * Any environment variable with this
+ * classification has at least one other
+ * classification
+ */
+ LIBENV_SU_SAFE /* = 26 */
+};
+
+/**
+ * Environment variable name and classification
+ */
+struct libenv_variable {
+ /**
+ * The name of the environment variable
+ */
+ const char *name;
+
+ /**
+ * Bitset of `enum libenv_class`'s the variable
+ * is classified under
+ *
+ * For any value `c` in `enum libenv_class` except
+ * `LIBENV_END`, `(.classes[c / 64] >> (c % 64)) & 1`
+ * is 1 iff the variable belongs to the class; however
+ * the application must verify that `c / 64` is less
+ * than the value output by `libenv_get_complete_list`
+ * to its first argument
+ *
+ * For the sake of simplicity, the lowest-valued bit
+ * in the first `uint64_t` is always 0
+ */
+ const uint64_t *classes;
+};
+
+
+/**
+ * Get the list of recognised environment variable,
+ * the list will container their names and classes
+ *
+ * This function does not read the current environment,
+ * and may return unset environemnt variables
+ *
+ * @param nclasswords_out Output parameter for the number of elements in each returned
+ * `struct libenv_variable`'s `.classes`, may be `NULL`
+ * @param count_out Output parameter for the number of elements in the returned list,
+ * sans a terminal `{NULL, NULL}` element, may be `NULL`
+ * @return Statically allocated list of all recognised environment variables
+ */
+LIBENV_RET_NONNULL__ const struct libenv_variable *libenv_get_complete_list(size_t *nclasswords_out, size_t *count_out);
+
+/**
+ * Get a list of environment variables names (which need not be set
+ * in the current environment) that fall into either of the specified
+ * variable classes
+ *
+ * @param classes_head,classes_tail List of variable classes, must end with `LIBENV_END`
+ * @return List of unique environment variable names, the caller should
+ * deallocate the returned list, when done with it, using the
+ * free(3) function, however the elements of the list are
+ * statically allocated and should not be deallocated or modified,
+ * `NULL` on failure
+ *
+ * @throws ENOMEM Not enought memory available to allocate the list
+ */
+LIBENV_MALLOC__ const char **libenv_vget_chosen_list(enum libenv_class, va_list);
+
+/**
+ * Get a list of environment variables names (which need not be set
+ * in the current environment) that fall into either of the specified
+ * variable classes
+ *
+ * @param classes_head... List of variable classes, must end with `LIBENV_END`
+ * @return List of unique environment variable names, the caller should
+ * deallocate the returned list, when done with it, using the
+ * free(3) function, however the elements of the list are
+ * statically allocated and should not be deallocated or modified,
+ * `NULL` on failure
+ *
+ * @throws ENOMEM Not enought memory available to allocate the list
+ */
+LIBENV_MALLOC__ const char **libenv_get_chosen_list(enum libenv_class, ... /*, LIBENV_END */);
+
+/**
+ * Given a list of environment variable names, remove the variables
+ * that belong to all of the specified environment variable classes
+ *
+ * @param variables `NULL`-terminated list environemnt variable names; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param classes The list of environment variable classes, must end with `LIBENV_END`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_vfilter_name_list(const char **, va_list);
+
+/**
+ * Given a list of environment variable names, remove the variables
+ * that belong to all of the specified environment variable classes
+ *
+ * @param variables `NULL`-terminated list environemnt variable names; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param ... The list of environment variable classes, must end with `LIBENV_END`,
+ * each argument must have the type `enum libenv_class`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_filter_name_list(const char **, /* enum libenv_class */ ... /*, LIBENV_END */);
+
+/**
+ * Given a list of environment variables, with values, remove the variables
+ * that belong to all of the specified environment variable classes
+ *
+ * @param variables `NULL`-terminated list environemnt variables; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param classes The list of environment variable classes, must end with `LIBENV_END`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_vfilter_variable_list(const char **, va_list);
+
+/**
+ * Given a list of environment variables, with values, remove the variables
+ * that belong to all of the specified environment variable classes
+ *
+ * @param variables `NULL`-terminated list environemnt variables; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param ... The list of environment variable classes, must end with `LIBENV_END`,
+ * each argument must have the type `enum libenv_class`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_filter_variable_list(const char **, /* enum libenv_class */ ... /*, LIBENV_END */);
+
+/**
+ * Given a list of environment variable names, remove any variable that
+ * does not belong to any of the specified environment variable classes
+ *
+ * @param variables `NULL`-terminated list environemnt variable names; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param classes The list of environment variable classes, must end with `LIBENV_END`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_vselect_name_list(const char **, va_list);
+
+/**
+ * Given a list of environment variable names, remove any variable that
+ * does not belong to any of the specified environment variable classes
+ *
+ * @param variables `NULL`-terminated list environemnt variable names; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param ... The list of environment variable classes, must end with `LIBENV_END`,
+ * each argument must have the type `enum libenv_class`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_select_name_list(const char **, /* enum libenv_class */ ... /*, LIBENV_END */);
+
+/**
+ * Given a list of environment variables, with values, remove any variable
+ * that does not belong to any of the specified environment variable classes
+ *
+ * @param variables `NULL`-terminated list environemnt variables; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param classes The list of environment variable classes, must end with `LIBENV_END`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_vselect_variable_list(const char **, va_list);
+
+/**
+ * Given a list of environment variables, with values, remove any variable
+ * that does not belong to any of the specified environment variable classes
+ *
+ * @param variables `NULL`-terminated list environemnt variables; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param ... The list of environment variable classes, must end with `LIBENV_END`,
+ * each argument must have the type `enum libenv_class`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_select_variable_list(const char **, /* enum libenv_class */ ... /*, LIBENV_END */);
+
+/**
+ * Given a list of environment variable names, remove the variables
+ * that belong to all of the specified environment variable classes
+ *
+ * Any element removed from `variables` will be deallocated using
+ * the free(3) function
+ *
+ * @param variables `NULL`-terminated list environemnt variable names; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param classes The list of environment variable classes, must end with `LIBENV_END`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_vfilter_name_list_with_dealloc(char **, va_list);
+
+/**
+ * Given a list of environment variable names, remove the variables
+ * that belong to all of the specified environment variable classes
+ *
+ * Any element removed from `variables` will be deallocated using
+ * the free(3) function
+ *
+ * @param variables `NULL`-terminated list environemnt variable names; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param ... The list of environment variable classes, must end with `LIBENV_END`,
+ * each argument must have the type `enum libenv_class`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_filter_name_list_with_dealloc(char **, /* enum libenv_class */ ... /*, LIBENV_END */);
+
+/**
+ * Given a list of environment variables, with values, remove the variables
+ * that belong to all of the specified environment variable classes
+ *
+ * Any element removed from `variables` will be deallocated using
+ * the free(3) function
+ *
+ * @param variables `NULL`-terminated list environemnt variables; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param classes The list of environment variable classes, must end with `LIBENV_END`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_vfilter_variable_list_with_dealloc(char **, va_list);
+
+/**
+ * Given a list of environment variables, with values, remove the variables
+ * that belong to all of the specified environment variable classes
+ *
+ * Any element removed from `variables` will be deallocated using
+ * the free(3) function
+ *
+ * @param variables `NULL`-terminated list environemnt variables; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param ... The list of environment variable classes, must end with `LIBENV_END`,
+ * each argument must have the type `enum libenv_class`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_filter_variable_list_with_dealloc(char **, /* enum libenv_class */ ... /*, LIBENV_END */);
+
+/**
+ * Given a list of environment variable names, remove any variable that
+ * does not belong to any of the specified environment variable classes
+ *
+ * Any element removed from `variables` will be deallocated using
+ * the free(3) function
+ *
+ * @param variables `NULL`-terminated list environemnt variable names; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param classes The list of environment variable classes, must end with `LIBENV_END`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_vselect_name_list_with_dealloc(char **, va_list);
+
+/**
+ * Given a list of environment variable names, remove any variable that
+ * does not belong to any of the specified environment variable classes
+ *
+ * Any element removed from `variables` will be deallocated using
+ * the free(3) function
+ *
+ * @param variables `NULL`-terminated list environemnt variable names; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param ... The list of environment variable classes, must end with `LIBENV_END`,
+ * each argument must have the type `enum libenv_class`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_select_name_list_with_dealloc(char **, /* enum libenv_class */ ... /*, LIBENV_END */);
+
+/**
+ * Given a list of environment variables, with values, remove any variable
+ * that does not belong to any of the specified environment variable classes
+ *
+ * Any element removed from `variables` will be deallocated using
+ * the free(3) function
+ *
+ * @param variables `NULL`-terminated list environemnt variables; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param classes The list of environment variable classes, must end with `LIBENV_END`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_vselect_variable_list_with_dealloc(char **, va_list);
+
+/**
+ * Given a list of environment variables, with values, remove any variable
+ * that does not belong to any of the specified environment variable classes
+ *
+ * Any element removed from `variables` will be deallocated using
+ * the free(3) function
+ *
+ * @param variables `NULL`-terminated list environemnt variables; may be `NULL`,
+ * which causes the function to return 0; unless `NULL` the list
+ * will be updated
+ * @param ... The list of environment variable classes, must end with `LIBENV_END`,
+ * each argument must have the type `enum libenv_class`
+ * @return The new number of elements in `variables`; `variables[return]` will
+ * be `NULL` provided that `variables` itself it not `NULL`
+ */
+size_t libenv_select_variable_list_with_dealloc(char **, /* enum libenv_class */ ... /*, LIBENV_END */);
+
+
+#undef LIBENV_MALLOC__
+#undef LIBENV_RET_NONNULL__
+
+#endif
diff --git a/libenv_class.3 b/libenv_class.3
new file mode 120000
index 0000000..bda9b00
--- /dev/null
+++ b/libenv_class.3
@@ -0,0 +1 @@
+enum_libenv_class.3 \ No newline at end of file
diff --git a/libenv_filter_name_list.3 b/libenv_filter_name_list.3
new file mode 100644
index 0000000..8f9d44d
--- /dev/null
+++ b/libenv_filter_name_list.3
@@ -0,0 +1,82 @@
+.TH LIBENV_FILTER_NAME_LIST 3 libenv
+.SH NAME
+libenv_filter_name_list - Remove unwanted environment variables
+
+.SH SYNOPSIS
+.nf
+#include <libenv.h>
+
+size_t libenv_filter_name_list(const char **\fIvariables\fP, /* enum libenv_class */ ... /*, LIBENV_END */);
+size_t libenv_vfilter_name_list(const char **\fIvariables\fP, va_list);
+size_t libenv_filter_name_list_with_dealloc(char **\fIvariables\fP, /* enum libenv_class */ ... /*, LIBENV_END */);
+size_t libenv_vfilter_name_list_with_dealloc(char **\fIvariables\fP, va_list);
+.fi
+.PP
+Link with
+.IR -lenv .
+
+.SH DESCRIPTION
+The
+.BR libenv_filter_name_list ()
+function removes element in
+.I variables
+that matches the name of an environment variable that
+belong to all of the environment variable classes listed
+after the
+.I variables
+argument. The list must end with
+.I LIBENV_END
+to mark indicate to the function that there are no
+more arguments to read.
+.PP
+.I variables
+should be a
+.I NULL
+terminated list, but may be
+.IR NULL .
+.PP
+The
+.BR libenv_filter_name_list_with_dealloc ()
+fucntion is a variant of the
+.BR libenv_filter_name_list ()
+function that deallocates, using the
+.BR free (3)
+function, any remove element.
+.PP
+The
+.BR libenv_vfilter_name_list ()
+and
+.BR libenv_vfilter_name_list_with_dealloc ()
+functions are variants of the
+.BR libenv_filter_name_list ()
+and
+.BR libenv_filter_name_list_with_dealloc ()
+functions, respectively, that uses
+.I va_list
+instead of being properly variadic.
+
+.SH RETURN VALUE
+The
+.BR libenv_filter_name_list (),
+.BR libenv_vfilter_name_list (),
+.BR libenv_filter_name_list_with_dealloc (),
+and
+.BR libenv_vfilter_name_list_with_dealloc ()
+functions return the new number of elements in
+.IR variables ,
+exclucing the
+.I NULL
+element at the end of the list.
+0 if
+.I variables
+is
+.IR NULL .
+
+.SH ERRORS
+None.
+
+.SH SEE ALSO
+.BR libenv (7),
+.BR enum_libenv_class (3),
+.BR libenv_filter_variable_list (3),
+.BR libenv_select_name_list (3).
diff --git a/libenv_filter_name_list.c b/libenv_filter_name_list.c
new file mode 100644
index 0000000..bfcf3a2
--- /dev/null
+++ b/libenv_filter_name_list.c
@@ -0,0 +1,15 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_filter_name_list(const char **variables, ...)
+{
+ va_list classes;
+ va_start(classes, variables);
+ return libenv_vfilter_name_list(variables, classes);
+ va_end(classes);
+}
+
+
+/* TODO test */
diff --git a/libenv_filter_name_list_with_dealloc.3 b/libenv_filter_name_list_with_dealloc.3
new file mode 120000
index 0000000..2659ef1
--- /dev/null
+++ b/libenv_filter_name_list_with_dealloc.3
@@ -0,0 +1 @@
+libenv_filter_name_list.3 \ No newline at end of file
diff --git a/libenv_filter_name_list_with_dealloc.c b/libenv_filter_name_list_with_dealloc.c
new file mode 100644
index 0000000..986be3b
--- /dev/null
+++ b/libenv_filter_name_list_with_dealloc.c
@@ -0,0 +1,15 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_filter_name_list_with_dealloc(char **variables, ...)
+{
+ va_list classes;
+ va_start(classes, variables);
+ return libenv_vfilter_name_list_with_dealloc(variables, classes);
+ va_end(classes);
+}
+
+
+/* TODO test */
diff --git a/libenv_filter_variable_list.3 b/libenv_filter_variable_list.3
new file mode 100644
index 0000000..641f162
--- /dev/null
+++ b/libenv_filter_variable_list.3
@@ -0,0 +1,84 @@
+.TH LIBENV_FILTER_VARIABLE_LIST 3 libenv
+.SH NAME
+libenv_filter_variable_list - Remove unwanted environment variables
+
+.SH SYNOPSIS
+.nf
+#include <libenv.h>
+
+size_t libenv_filter_variable_list(const char **\fIvariables\fP, /* enum libenv_class */ ... /*, LIBENV_END */);
+size_t libenv_vfilter_variable_list(const char **\fIvariables\fP, va_list);
+size_t libenv_filter_variable_list_with_dealloc(char **\fIvariables\fP, /* enum libenv_class */ ... /*, LIBENV_END */);
+size_t libenv_vfilter_variable_list_with_dealloc(char **\fIvariables\fP, va_list);
+.fi
+.PP
+Link with
+.IR -lenv .
+
+.SH DESCRIPTION
+The
+.BR libenv_filter_variable_list ()
+function removes element in
+.I variables
+that matches the name, optionally with an equals sign
+.RB ( = )
+followed by anything, of an environment variable that
+belong to all of the environment variable classes listed
+after the
+.I variables
+argument. The list must end with
+.I LIBENV_END
+to mark indicate to the function that there are no
+more arguments to read.
+.PP
+.I variables
+should be a
+.I NULL
+terminated list, but may be
+.IR NULL .
+.PP
+The
+.BR libenv_filter_variable_list_with_dealloc ()
+fucntion is a variant of the
+.BR libenv_filter_variable_list ()
+function that deallocates, using the
+.BR free (3)
+function, any remove element.
+.PP
+The
+.BR libenv_vfilter_variable_list ()
+and
+.BR libenv_vfilter_variable_list_with_dealloc ()
+functions are variants of the
+.BR libenv_filter_variable_list ()
+and
+.BR libenv_filter_variable_list_with_dealloc ()
+functions, respectively, that uses
+.I va_list
+instead of being properly variadic.
+
+.SH RETURN VALUE
+The
+.BR libenv_filter_variable_list (),
+.BR libenv_vfilter_variable_list (),
+.BR libenv_filter_variable_list_with_dealloc (),
+and
+.BR libenv_vfilter_variable_list_with_dealloc ()
+functions return the new number of elements in
+.IR variables ,
+exclucing the
+.I NULL
+element at the end of the list.
+0 if
+.I variables
+is
+.IR NULL .
+
+.SH ERRORS
+None.
+
+.SH SEE ALSO
+.BR libenv (7),
+.BR enum_libenv_class (3),
+.BR libenv_filter_name_list (3),
+.BR libenv_select_variable_list (3).
diff --git a/libenv_filter_variable_list.c b/libenv_filter_variable_list.c
new file mode 100644
index 0000000..fa02ef9
--- /dev/null
+++ b/libenv_filter_variable_list.c
@@ -0,0 +1,15 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_filter_variable_list(const char **variables, ...)
+{
+ va_list classes;
+ va_start(classes, variables);
+ return libenv_vfilter_variable_list(variables, classes);
+ va_end(classes);
+}
+
+
+/* TODO test */
diff --git a/libenv_filter_variable_list_with_dealloc.3 b/libenv_filter_variable_list_with_dealloc.3
new file mode 120000
index 0000000..93f6429
--- /dev/null
+++ b/libenv_filter_variable_list_with_dealloc.3
@@ -0,0 +1 @@
+libenv_filter_variable_list.3 \ No newline at end of file
diff --git a/libenv_filter_variable_list_with_dealloc.c b/libenv_filter_variable_list_with_dealloc.c
new file mode 100644
index 0000000..6332659
--- /dev/null
+++ b/libenv_filter_variable_list_with_dealloc.c
@@ -0,0 +1,15 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_filter_variable_list_with_dealloc(char **variables, ...)
+{
+ va_list classes;
+ va_start(classes, variables);
+ return libenv_vfilter_variable_list_with_dealloc(variables, classes);
+ va_end(classes);
+}
+
+
+/* TODO test */
diff --git a/libenv_get_chosen_list.3 b/libenv_get_chosen_list.3
new file mode 100644
index 0000000..0b87403
--- /dev/null
+++ b/libenv_get_chosen_list.3
@@ -0,0 +1,69 @@
+.TH LIBENV_GET_CHOSEN_LIST 3 libenv
+.SH NAME
+libenv_get_chosen_list - List recognised environment variables by class
+
+.SH SYNOPSIS
+.nf
+#include <libenv.h>
+
+const char **libenv_get_chosen_list(enum libenv_class, ... /*, LIBENV_END */);
+const char **libenv_vget_chosen_list(enum libenv_class, va_list);
+.fi
+.PP
+Link with
+.IR -lenv .
+
+.SH DESCRIPTION
+The
+.BR libenv_get_chosen_list ()
+function returns a
+.I NULL
+terminated list of the names of all environment variables, that it knows of,
+regardless if they are set in the environemnt, and that belong to at least
+one of the environment variable classes listed in the functions argument list.
+The argument list must be termianted with
+.I LIBENV_END
+so that the function knonws when there are no more arguments to read.
+.PP
+The
+.BR libenv_vget_chosen_list ()
+function is a variant of the
+.BR libenv_get_chosen_list ()
+function that uses
+.I va_list
+rather than being properly variadic.
+
+.SH RETURN VALUE
+Upon successful completion, the
+.BR libenv_get_chosen_list ()
+and
+.BR libenv_vget_chosen_list ()
+functions return a
+.IR NULL -
+terminated list of statically allocated
+strings, representing environment variable names.
+The returned list, but not it's element, shall
+be deallocated using the
+.BR free (3)
+function. On failure
+.I NULL
+is returned and
+.I errno
+is appropriately set to describe the error.
+
+.SH ERRORS
+The
+.BR libenv_get_chosen_list ()
+and
+.BR libenv_vget_chosen_list ()
+functions may fail if:
+.TP
+.B ENOMEM
+Insufficient memory available.
+
+.SH SEE ALSO
+.BR libenv (7),
+.BR enum_libenv_class (3),
+.BR libenv_get_complete_list (3),
+.BR libenv_filter_variable_list (3),
+.BR libenv_select_variable_list (3).
diff --git a/libenv_get_chosen_list.c b/libenv_get_chosen_list.c
new file mode 100644
index 0000000..f4975fd
--- /dev/null
+++ b/libenv_get_chosen_list.c
@@ -0,0 +1,15 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+const char **
+libenv_get_chosen_list(enum libenv_class classes_head, ...)
+{
+ va_list classes_tail;
+ va_start(classes_tail, classes_head);
+ return libenv_vget_chosen_list(classes_head, classes_tail);
+ va_end(classes_tail);
+}
+
+
+/* TODO test */
diff --git a/libenv_get_complete_list.3 b/libenv_get_complete_list.3
new file mode 100644
index 0000000..83038a3
--- /dev/null
+++ b/libenv_get_complete_list.3
@@ -0,0 +1,82 @@
+.TH LIBENV_GET_COMPLETE_LIST 3 libenv
+.SH NAME
+libenv_get_complete_list - List all recognised environment variables
+
+.SH SYNOPSIS
+.nf
+#include <libenv.h>
+
+struct libenv_variable {
+ const char *\fIname\fP;
+ const uint64_t *\fIclasses\fP;
+};
+
+const struct libenv_variable *libenv_get_complete_list(size_t *\fInclasswords_out\fP, size_t *\fIcount_out\fP);
+.fi
+.PP
+Link with
+.IR -lenv .
+
+.SH DESCRIPTION
+The
+.BR libenv_get_complete_list ()
+function returns a list of all environment variables the library knows of,
+regardless of whether they are set in the environment. The function returns
+a list of
+.I struct libenv_variable
+elements, for each of them,
+.I .name
+will be set to the name of the environment variable and
+.I .classes
+will be set to a bit field of classes the environment variable
+belongs to. If
+.IR (.classes[i]>>b)&1 ,
+then the
+.BR "enum libenv_class" (3)
+member with the value
+.I i*64+b
+describes a class the environment variable belongs to. (Make sure that you
+do not compare against values greeater than or equal to
+.IR *nclasswords_out*64 .)
+The bit corresponding to
+.I LIBENV_END
+will always be 0.
+.PP
+Unless
+.I nclasswords_out
+is
+.IR NULL ,
+.I *nclasswords_out
+will be set to the number of elements
+.RB ( uint64_t 's)
+in each
+.I .classes
+for each returned
+.IR "struct libenv_variable" .
+.PP
+Unless
+.I count_out
+is
+.IR NULL ,
+.I *count_out
+will be set to the number of returned environment variables.
+
+.SH RETURN VALUE
+The
+.BR libenv_get_complete_list (3)
+function returns a statically allocated list of environment variables
+along with the classifications; the list will contain
+.I *count_out
+(as set when the function returns) elements, plus one extra element,
+at the end, having both its fields set to
+.IR NULL .
+
+.SH ERRORS
+None.
+
+.SH SEE ALSO
+.BR libenv (7),
+.BR enum_libenv_class (3),
+.BR libenv_get_chosen_list (3),
+.BR libenv_filter_variable_list (3),
+.BR libenv_select_variable_list (3).
diff --git a/libenv_get_complete_list.c b/libenv_get_complete_list.c
new file mode 100644
index 0000000..9a542c9
--- /dev/null
+++ b/libenv_get_complete_list.c
@@ -0,0 +1,211 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+#define NCLASSWORDS 1U
+
+
+#define _(E) ((uint64_t)1 << (E))
+
+#define SU_SAFE _(LIBENV_SU_SAFE)
+#define SU_UNSAFE _(LIBENV_SU_UNSAFE)
+#define LOGIN_SAFE _(LIBENV_LOGIN_SAFE)
+#define LOGIN_UNSAFE _(LIBENV_LOGIN_UNSAFE)
+#define REMOTE_SAFE _(LIBENV_REMOTE_SAFE)
+#define REMOTE_UNSAFE _(LIBENV_REMOTE_UNSAFE)
+#define PATH (_(LIBENV_PATH) | REMOTE_UNSAFE)
+
+#define DECLARE(VAR, ENUMS_)\
+ static const uint64_t VAR[NCLASSWORDS] = {ENUMS_}
+
+DECLARE(classes__display, _(LIBENV_DISPLAY) | SU_SAFE | LOGIN_SAFE | REMOTE_UNSAFE);
+DECLARE(classes__display_config, _(LIBENV_DISPLAY_CONFIG) | SU_SAFE | LOGIN_SAFE | REMOTE_UNSAFE);
+DECLARE(classes__desktop, _(LIBENV_DESKTOP) | SU_SAFE | LOGIN_SAFE | REMOTE_SAFE);
+DECLARE(classes__terminal_caps, _(LIBENV_TERMINAL_CAPS) | SU_SAFE | LOGIN_SAFE | REMOTE_SAFE);
+DECLARE(classes__local_terminal, _(LIBENV_LOCAL_TERMINAL) | SU_SAFE | LOGIN_SAFE | REMOTE_UNSAFE);
+DECLARE(classes__locale, _(LIBENV_LOCALE) | SU_SAFE | LOGIN_UNSAFE | REMOTE_UNSAFE);
+DECLARE(classes__locale__path, _(LIBENV_LOCALE) | SU_SAFE | LOGIN_UNSAFE | PATH);
+DECLARE(classes__timezone, _(LIBENV_TIMEZONE) | SU_SAFE | LOGIN_UNSAFE | REMOTE_UNSAFE);
+DECLARE(classes__timezone__path, _(LIBENV_TIMEZONE) | SU_SAFE | LOGIN_UNSAFE | PATH);
+DECLARE(classes__session, _(LIBENV_SESSION) | SU_SAFE | LOGIN_SAFE | REMOTE_UNSAFE);
+DECLARE(classes__theme_config, _(LIBENV_THEME_CONFIG) | SU_SAFE | LOGIN_UNSAFE | REMOTE_SAFE);
+DECLARE(classes__theme_plugin, _(LIBENV_THEME_PLUGIN) | SU_UNSAFE | LOGIN_UNSAFE | REMOTE_UNSAFE);
+DECLARE(classes__internet, _(LIBENV_INTERNET) | SU_SAFE | LOGIN_UNSAFE | REMOTE_UNSAFE);
+DECLARE(classes__audio, _(LIBENV_AUDIO) | SU_SAFE | LOGIN_SAFE | REMOTE_UNSAFE);
+DECLARE(classes__user, _(LIBENV_USER) | SU_UNSAFE | LOGIN_UNSAFE | REMOTE_UNSAFE);
+DECLARE(classes__applications, _(LIBENV_APPLICATIONS) | SU_SAFE | LOGIN_UNSAFE | REMOTE_UNSAFE);
+DECLARE(classes__preferences, _(LIBENV_PREFERENCES) | SU_SAFE | LOGIN_UNSAFE | REMOTE_SAFE);
+DECLARE(classes__system_paths, _(LIBENV_SYSTEM_PATHS) | SU_SAFE | LOGIN_UNSAFE | PATH);
+DECLARE(classes__user_paths, _(LIBENV_USER_PATHS) | SU_SAFE | LOGIN_UNSAFE | PATH);
+DECLARE(classes__pwd, _(LIBENV_PWD) | SU_SAFE | LOGIN_UNSAFE | PATH);
+DECLARE(classes__exec__path, _(LIBENV_EXEC) | SU_SAFE | LOGIN_UNSAFE | PATH);
+
+#undef _
+#undef SU_SAFE
+#undef SU_UNSAFE
+#undef LOGIN_SAFE
+#undef LOGIN_UNSAFE
+#undef REMOTE_SAFE
+#undef REMOTE_UNSAFE
+#undef PATH
+#undef DECLARE
+#define V(S) {S, CLASSES}
+
+
+static struct libenv_variable list[] = {
+
+#define CLASSES classes__display
+ V("DISPLAY"),
+ V("WAYLAND_DISPLAY"),
+ V("XAUTHORITY"),
+ V("XDG_SEAT"),
+ V("XDG_SEAT_PATH"),
+ V("XDG_VTNR"),
+#undef CLASSES
+
+#define CLASSES classes__display_config
+ V("SDL_VIDEO_FULLSCREEN_DISPLAY"),
+ V("XMODIFIERS"),
+#undef CLASSES
+
+#define CLASSES classes__desktop
+ V("DESKTOP_SESSION"),
+ V("GTK_CSD"),
+ V("XDG_SESSION_PATH"),
+ V("XDG_SESSION_DESKTOP"),
+ V("XDG_SESSION_TYPE"),
+ V("XDG_SESSION_CLASS"),
+ V("XDG_SESSION_ID"),
+ V("_JAVA_AWT_WM_NOREPARENTING"),
+#undef CLASSES
+
+#define CLASSES classes__terminal_caps
+ V("TERM"),
+ V("COLORTERM"),
+ V("VTE_VERSION"),
+#undef CLASSES
+
+#define CLASSES classes__local_terminal
+ V("TERMINATOR_UUID"),
+#undef CLASSES
+
+#define CLASSES classes__locale
+ V("LANG"),
+ V("LANGUAGE"),
+ V("LOCALE"),
+ V("LC_CTYPE"),
+ V("LC_NUMERIC"),
+ V("LC_TIME"),
+ V("LC_COLLATE"),
+ V("LC_MONETARY"),
+ V("LC_MESSAGES"),
+ V("LC_PAPER"),
+ V("LC_NAME"),
+ V("LC_ADDRESS"),
+ V("LC_TELEPHONE"),
+ V("LC_MEASUREMENT"),
+ V("LC_IDENTIFICATION"),
+ V("LC_ALL"),
+#undef CLASSES
+
+#define CLASSES classes__locale__path
+ V("LOCPATH"),
+ V("NLSPATH"),
+#undef CLASSES
+
+#define CLASSES classes__timezone
+ V("TZ"),
+#undef CLASSES
+
+#define CLASSES classes__timezone__path
+ V("TZDIR"),
+#undef CLASSES
+
+#define CLASSES classes__session
+ V("SSH_CLIENT"),
+ V("SSH_CONNECTION"),
+ V("SSH_TTY"),
+#undef CLASSES
+
+#define CLASSES classes__theme_config
+ V("LS_COLORS"),
+#undef CLASSES
+
+#define CLASSES classes__theme_plugin
+ V("GTK_THEME"),
+ V("QT_STYLE_OVERRIDE"),
+ V("QT_QPA_PLATFORMTHEME"),
+#undef CLASSES
+
+#define CLASSES classes__internet
+ V("ftp_proxy"),
+ V("http_proxy"),
+#undef CLASSES
+
+#define CLASSES classes__audio
+ V("MAIN_ALSA_MIXER"),
+ V("MAIN_ALSA_CARD"),
+#undef CLASSES
+
+#define CLASSES classes__user
+ V("LOGNAME"),
+ V("HOME"),
+ V("SHELL"),
+#undef CLASSES
+
+#define CLASSES classes__applications
+ V("EDITOR"),
+ V("VISUAL"),
+ V("BROWSER"),
+ V("PAGER"),
+#undef CLASSES
+
+#define CLASSES classes__preferences
+ V("MANSECT"),
+ V("_JAVA_OPTIONS"),
+#undef CLASSES
+
+#define CLASSES classes__system_paths
+ V("PATH"),
+ V("XDG_DATA_DIRS"),
+ V("XDG_CONFIG_DIRS"),
+ V("MANPATH"),
+ V("INFODIR"),
+ V("JAVA_HOME"),
+#undef CLASSES
+
+#define CLASSES classes__user_paths
+ V("XDG_SPOOL_HOME"),
+ V("XDG_CACHE_HOME"),
+ V("XDG_STATE_HOME"),
+ V("XDG_RUNTIME_DIR"),
+ V("XDG_DATA_HOME"),
+ V("XDG_CONFIG_HOME"),
+ V("GNUPGHOME"),
+ V("MPLAYER_HOME"),
+#undef CLASSES
+
+#define CLASSES classes__pwd
+ V("PWD"),
+ V("OLDPWD"),
+#undef CLASSES
+
+#define CLASSES classes__exec__path
+ V("_"),
+#undef CLASSES
+
+ {NULL, NULL}
+};
+
+
+#undef V
+
+
+const struct libenv_variable *
+libenv_get_complete_list(size_t *nclasswords_out, size_t *count_out) /* TODO test */
+{
+ if (nclasswords_out)
+ *nclasswords_out = NCLASSWORDS;
+ if (count_out)
+ *count_out = sizeof(list) / sizeof(*list) - 1U;
+ return list;
+}
diff --git a/libenv_select_name_list.3 b/libenv_select_name_list.3
new file mode 100644
index 0000000..6addcd1
--- /dev/null
+++ b/libenv_select_name_list.3
@@ -0,0 +1,82 @@
+.TH LIBENV_SELECT_NAME_LIST 3 libenv
+.SH NAME
+libenv_select_name_list - Keep wanted environment variables
+
+.SH SYNOPSIS
+.nf
+#include <libenv.h>
+
+size_t libenv_select_name_list(const char **\fIvariables\fP, /* enum libenv_class */ ... /*, LIBENV_END */);
+size_t libenv_vselect_name_list(const char **\fIvariables\fP, va_list \fIclasses\fP);
+size_t libenv_select_name_list_with_dealloc(char **\fIvariables\fP, /* enum libenv_class */ ... /*, LIBENV_END */);
+size_t libenv_vselect_name_list_with_dealloc(char **\fIvariables\fP, va_list \fIclasses\fP);
+.fi
+.PP
+Link with
+.IR -lenv .
+
+.SH DESCRIPTION
+The
+.BR libenv_select_name_list ()
+function removes element in
+.I variables
+that matches the name of an environment variable that
+do not belong to ant of the environment variable classes
+listed after the
+.I variables
+argument. The list must end with
+.I LIBENV_END
+to mark indicate to the function that there are no
+more arguments to read.
+.PP
+.I variables
+should be a
+.I NULL
+terminated list, but may be
+.IR NULL .
+.PP
+The
+.BR libenv_select_name_list_with_dealloc ()
+fucntion is a variant of the
+.BR libenv_select_name_list ()
+function that deallocates, using the
+.BR free (3)
+function, any remove element.
+.PP
+The
+.BR libenv_vselect_name_list ()
+and
+.BR libenv_vselect_name_list_with_dealloc ()
+functions are variants of the
+.BR libenv_select_name_list ()
+and
+.BR libenv_select_name_list_with_dealloc ()
+functions, respectively, that uses
+.I va_list
+instead of being properly variadic.
+
+.SH RETURN VALUE
+The
+.BR libenv_select_name_list (),
+.BR libenv_vselect_name_list (),
+.BR libenv_select_name_list_with_dealloc (),
+and
+.BR libenv_vselect_name_list_with_dealloc ()
+functions return the new number of elements in
+.IR variables ,
+exclucing the
+.I NULL
+element at the end of the list.
+0 if
+.I variables
+is
+.IR NULL .
+
+.SH ERRORS
+None.
+
+.SH SEE ALSO
+.BR libenv (7),
+.BR enum_libenv_class (3),
+.BR libenv_select_variable_list (3),
+.BR libenv_filter_name_list (3).
diff --git a/libenv_select_name_list.c b/libenv_select_name_list.c
new file mode 100644
index 0000000..705e499
--- /dev/null
+++ b/libenv_select_name_list.c
@@ -0,0 +1,15 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_select_name_list(const char **variables, ...)
+{
+ va_list classes;
+ va_start(classes, variables);
+ return libenv_vselect_name_list(variables, classes);
+ va_end(classes);
+}
+
+
+/* TODO test */
diff --git a/libenv_select_name_list_with_dealloc.3 b/libenv_select_name_list_with_dealloc.3
new file mode 120000
index 0000000..cdc3847
--- /dev/null
+++ b/libenv_select_name_list_with_dealloc.3
@@ -0,0 +1 @@
+libenv_select_name_list.3 \ No newline at end of file
diff --git a/libenv_select_name_list_with_dealloc.c b/libenv_select_name_list_with_dealloc.c
new file mode 100644
index 0000000..b6bc0ca
--- /dev/null
+++ b/libenv_select_name_list_with_dealloc.c
@@ -0,0 +1,15 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_select_name_list_with_dealloc(char **variables, ...)
+{
+ va_list classes;
+ va_start(classes, variables);
+ return libenv_vselect_name_list_with_dealloc(variables, classes);
+ va_end(classes);
+}
+
+
+/* TODO test */
diff --git a/libenv_select_variable_list.3 b/libenv_select_variable_list.3
new file mode 100644
index 0000000..2ec8427
--- /dev/null
+++ b/libenv_select_variable_list.3
@@ -0,0 +1,84 @@
+.TH LIBENV_SELECT_VARIABLE_LIST 3 libenv
+.SH NAME
+libenv_select_variable_list - Keep wanted environment variables
+
+.SH SYNOPSIS
+.nf
+#include <libenv.h>
+
+size_t libenv_select_variable_list(const char **\fIvariables\fP, /* enum libenv_class */ ... /*, LIBENV_END */);
+size_t libenv_vselect_variable_list(const char **\fIvariables\fP, va_list \fIclasses\fP);
+size_t libenv_select_variable_list_with_dealloc(char **\fIvariables\fP, /* enum libenv_class */ ... /*, LIBENV_END */);
+size_t libenv_vselect_variable_list_with_dealloc(char **\fIvariables\fP, va_list \fIclasses\fP);
+.fi
+.PP
+Link with
+.IR -lenv .
+
+.SH DESCRIPTION
+The
+.BR libenv_select_variable_list ()
+function removes element in
+.I variables
+that matches the name, optionally with an equals sign
+.RB ( = )
+followed by anything, of an environment variable that
+do not belong to any of the environment variable classes
+listed after the
+.I variables
+argument. The list must end with
+.I LIBENV_END
+to mark indicate to the function that there are no
+more arguments to read.
+.PP
+.I variables
+should be a
+.I NULL
+terminated list, but may be
+.IR NULL .
+.PP
+The
+.BR libenv_select_variable_list_with_dealloc ()
+fucntion is a variant of the
+.BR libenv_select_variable_list ()
+function that deallocates, using the
+.BR free (3)
+function, any remove element.
+.PP
+The
+.BR libenv_vselect_variable_list ()
+and
+.BR libenv_vselect_variable_list_with_dealloc ()
+functions are variants of the
+.BR libenv_select_variable_list ()
+and
+.BR libenv_select_variable_list_with_dealloc ()
+functions, respectively, that uses
+.I va_list
+instead of being properly variadic.
+
+.SH RETURN VALUE
+The
+.BR libenv_select_variable_list (),
+.BR libenv_vselect_variable_list (),
+.BR libenv_select_variable_list_with_dealloc (),
+and
+.BR libenv_vselect_variable_list_with_dealloc ()
+functions return the new number of elements in
+.IR variables ,
+exclucing the
+.I NULL
+element at the end of the list.
+0 if
+.I variables
+is
+.IR NULL .
+
+.SH ERRORS
+None.
+
+.SH SEE ALSO
+.BR libenv (7),
+.BR enum_libenv_class (3),
+.BR libenv_select_name_list (3),
+.BR libenv_filter_variable_list (3).
diff --git a/libenv_select_variable_list.c b/libenv_select_variable_list.c
new file mode 100644
index 0000000..ff902af
--- /dev/null
+++ b/libenv_select_variable_list.c
@@ -0,0 +1,15 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_select_variable_list(const char **variables, ...)
+{
+ va_list classes;
+ va_start(classes, variables);
+ return libenv_vselect_variable_list(variables, classes);
+ va_end(classes);
+}
+
+
+/* TODO test */
diff --git a/libenv_select_variable_list_with_dealloc.3 b/libenv_select_variable_list_with_dealloc.3
new file mode 120000
index 0000000..a3d0b53
--- /dev/null
+++ b/libenv_select_variable_list_with_dealloc.3
@@ -0,0 +1 @@
+libenv_select_variable_list.3 \ No newline at end of file
diff --git a/libenv_select_variable_list_with_dealloc.c b/libenv_select_variable_list_with_dealloc.c
new file mode 100644
index 0000000..0018577
--- /dev/null
+++ b/libenv_select_variable_list_with_dealloc.c
@@ -0,0 +1,15 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_select_variable_list_with_dealloc(char **variables, ...)
+{
+ va_list classes;
+ va_start(classes, variables);
+ return libenv_vselect_variable_list_with_dealloc(variables, classes);
+ va_end(classes);
+}
+
+
+/* TODO test */
diff --git a/libenv_variable.3 b/libenv_variable.3
new file mode 120000
index 0000000..1be54f7
--- /dev/null
+++ b/libenv_variable.3
@@ -0,0 +1 @@
+struct_libenv_variable.3 \ No newline at end of file
diff --git a/libenv_vfilter_name_list.3 b/libenv_vfilter_name_list.3
new file mode 120000
index 0000000..2659ef1
--- /dev/null
+++ b/libenv_vfilter_name_list.3
@@ -0,0 +1 @@
+libenv_filter_name_list.3 \ No newline at end of file
diff --git a/libenv_vfilter_name_list.c b/libenv_vfilter_name_list.c
new file mode 100644
index 0000000..7ed841a
--- /dev/null
+++ b/libenv_vfilter_name_list.c
@@ -0,0 +1,12 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_vfilter_name_list(const char **variables, va_list classes)
+{
+ return libenv_vprocess_list_without_dealloc__(variables, 0, classes, NO_HEAD, NAMES, FILTER);
+}
+
+
+/* TODO test */
diff --git a/libenv_vfilter_name_list_with_dealloc.3 b/libenv_vfilter_name_list_with_dealloc.3
new file mode 120000
index 0000000..a302738
--- /dev/null
+++ b/libenv_vfilter_name_list_with_dealloc.3
@@ -0,0 +1 @@
+libenv_vfilter_name_list.3 \ No newline at end of file
diff --git a/libenv_vfilter_name_list_with_dealloc.c b/libenv_vfilter_name_list_with_dealloc.c
new file mode 100644
index 0000000..5140c57
--- /dev/null
+++ b/libenv_vfilter_name_list_with_dealloc.c
@@ -0,0 +1,12 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_vfilter_name_list_with_dealloc(char **variables, va_list classes)
+{
+ return libenv_vprocess_list_with_dealloc__(variables, 0, classes, NO_HEAD, NAMES, FILTER);
+}
+
+
+/* TODO test */
diff --git a/libenv_vfilter_variable_list.3 b/libenv_vfilter_variable_list.3
new file mode 120000
index 0000000..93f6429
--- /dev/null
+++ b/libenv_vfilter_variable_list.3
@@ -0,0 +1 @@
+libenv_filter_variable_list.3 \ No newline at end of file
diff --git a/libenv_vfilter_variable_list.c b/libenv_vfilter_variable_list.c
new file mode 100644
index 0000000..6e8f371
--- /dev/null
+++ b/libenv_vfilter_variable_list.c
@@ -0,0 +1,12 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_vfilter_variable_list(const char **variables, va_list classes)
+{
+ return libenv_vprocess_list_without_dealloc__(variables, 0, classes, NO_HEAD, VARIABLES, FILTER);
+}
+
+
+/* TODO test */
diff --git a/libenv_vfilter_variable_list_with_dealloc.3 b/libenv_vfilter_variable_list_with_dealloc.3
new file mode 120000
index 0000000..bdbaea6
--- /dev/null
+++ b/libenv_vfilter_variable_list_with_dealloc.3
@@ -0,0 +1 @@
+libenv_vfilter_variable_list.3 \ No newline at end of file
diff --git a/libenv_vfilter_variable_list_with_dealloc.c b/libenv_vfilter_variable_list_with_dealloc.c
new file mode 100644
index 0000000..65431db
--- /dev/null
+++ b/libenv_vfilter_variable_list_with_dealloc.c
@@ -0,0 +1,12 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_vfilter_variable_list_with_dealloc(char **variables, va_list classes)
+{
+ return libenv_vprocess_list_with_dealloc__(variables, 0, classes, NO_HEAD, VARIABLES, FILTER);
+}
+
+
+/* TODO test */
diff --git a/libenv_vget_chosen_list.3 b/libenv_vget_chosen_list.3
new file mode 120000
index 0000000..8878673
--- /dev/null
+++ b/libenv_vget_chosen_list.3
@@ -0,0 +1 @@
+libenv_get_chosen_list.3 \ No newline at end of file
diff --git a/libenv_vget_chosen_list.c b/libenv_vget_chosen_list.c
new file mode 100644
index 0000000..2a5e1e6
--- /dev/null
+++ b/libenv_vget_chosen_list.c
@@ -0,0 +1,23 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+const char **
+libenv_vget_chosen_list(enum libenv_class classes_head, va_list classes_tail)
+{
+ size_t count;
+ const struct libenv_variable *vars;
+ const char **names;
+ size_t i;
+ vars = libenv_get_complete_list(NULL, &count);
+ names = malloc((count + 1U) * sizeof(*names));
+ if (!names)
+ return NULL;
+ for (i = 0; i < count; i++)
+ names[i] = vars[i].name;
+ libenv_vprocess_list_without_dealloc__(names, classes_head, classes_tail, HAVE_HEAD, NAMES, SELECT);
+ return names;
+}
+
+
+/* TODO test */
diff --git a/libenv_vprocess_list__.c b/libenv_vprocess_list__.c
new file mode 100644
index 0000000..1124a63
--- /dev/null
+++ b/libenv_vprocess_list__.c
@@ -0,0 +1,64 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+static int
+matches(const char *var, const struct libenv_variable *known, int is_name_only,
+ enum libenv_class classes_head, va_list classes_tail, int all, size_t nclasswords)
+{
+ size_t i, w, b;
+ for (; known->name; known++) {
+ for (i = 0;; i++)
+ if (var[i] != known->name[i])
+ break;
+ if (known->name[i])
+ continue;
+ if (var[i] == (is_name_only ? '\0' : '='))
+ goto found;
+ }
+ return 0;
+
+found:
+ for (; classes_head; classes_head = va_arg(classes_tail, enum libenv_class)) {
+ w = (size_t)classes_head / 64U;
+ b = (size_t)classes_head % 64U;
+ if (w >= nclasswords && ((known->classes[w] >> b) & 1)) {
+ if (!all)
+ return 1;
+ } else {
+ if (all)
+ return 0;
+ }
+ }
+ return all;
+}
+
+size_t
+libenv_vprocess_list__(void *variables_, enum libenv_class classes_head, va_list classes_tail,
+ int have_head, int names, int filter, int all, int dealloc)
+{
+ char **variables = variables_;
+ const struct libenv_variable *known;
+ size_t nclasswords;
+ size_t i, n = 0;
+ va_list classes_tail_2;
+
+ if (!variables)
+ return 0;
+ if (!have_head)
+ classes_head = va_arg(classes_tail, enum libenv_class);
+
+ known = libenv_get_complete_list(&nclasswords, NULL);
+
+ for (i = 0; variables[i]; i++) {
+ va_copy(classes_tail_2, classes_tail);
+ if (filter ^ matches(variables[i], known, names, classes_head, classes_tail_2, all, nclasswords))
+ variables[n++] = variables[i];
+ else if (dealloc)
+ free(variables[i]);
+ va_end(classes_tail_2);
+ }
+
+ variables[n] = NULL;
+ return n;
+}
diff --git a/libenv_vselect_name_list.3 b/libenv_vselect_name_list.3
new file mode 120000
index 0000000..cdc3847
--- /dev/null
+++ b/libenv_vselect_name_list.3
@@ -0,0 +1 @@
+libenv_select_name_list.3 \ No newline at end of file
diff --git a/libenv_vselect_name_list.c b/libenv_vselect_name_list.c
new file mode 100644
index 0000000..5eef51e
--- /dev/null
+++ b/libenv_vselect_name_list.c
@@ -0,0 +1,12 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_vselect_name_list(const char **variables, va_list classes)
+{
+ return libenv_vprocess_list_without_dealloc__(variables, 0, classes, NO_HEAD, NAMES, SELECT);
+}
+
+
+/* TODO test */
diff --git a/libenv_vselect_name_list_with_dealloc.3 b/libenv_vselect_name_list_with_dealloc.3
new file mode 120000
index 0000000..1e34bf7
--- /dev/null
+++ b/libenv_vselect_name_list_with_dealloc.3
@@ -0,0 +1 @@
+libenv_vselect_name_list.3 \ No newline at end of file
diff --git a/libenv_vselect_name_list_with_dealloc.c b/libenv_vselect_name_list_with_dealloc.c
new file mode 100644
index 0000000..95f35ed
--- /dev/null
+++ b/libenv_vselect_name_list_with_dealloc.c
@@ -0,0 +1,12 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_vselect_name_list_with_dealloc(char **variables, va_list classes)
+{
+ return libenv_vprocess_list_with_dealloc__(variables, 0, classes, NO_HEAD, NAMES, SELECT);
+}
+
+
+/* TODO test */
diff --git a/libenv_vselect_variable_list.3 b/libenv_vselect_variable_list.3
new file mode 120000
index 0000000..a3d0b53
--- /dev/null
+++ b/libenv_vselect_variable_list.3
@@ -0,0 +1 @@
+libenv_select_variable_list.3 \ No newline at end of file
diff --git a/libenv_vselect_variable_list.c b/libenv_vselect_variable_list.c
new file mode 100644
index 0000000..0e57710
--- /dev/null
+++ b/libenv_vselect_variable_list.c
@@ -0,0 +1,12 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_vselect_variable_list(const char **variables, va_list classes)
+{
+ return libenv_vprocess_list_without_dealloc__(variables, 0, classes, NO_HEAD, VARIABLES, SELECT);
+}
+
+
+/* TODO test */
diff --git a/libenv_vselect_variable_list_with_dealloc.3 b/libenv_vselect_variable_list_with_dealloc.3
new file mode 120000
index 0000000..aaa2e0e
--- /dev/null
+++ b/libenv_vselect_variable_list_with_dealloc.3
@@ -0,0 +1 @@
+libenv_vselect_variable_list.3 \ No newline at end of file
diff --git a/libenv_vselect_variable_list_with_dealloc.c b/libenv_vselect_variable_list_with_dealloc.c
new file mode 100644
index 0000000..cec9d7a
--- /dev/null
+++ b/libenv_vselect_variable_list_with_dealloc.c
@@ -0,0 +1,12 @@
+/* See LICENSE file for copyright and license details. */
+#include "common.h"
+
+
+size_t
+libenv_vselect_variable_list_with_dealloc(char **variables, va_list classes)
+{
+ return libenv_vprocess_list_with_dealloc__(variables, 0, classes, NO_HEAD, VARIABLES, SELECT);
+}
+
+
+/* TODO test */
diff --git a/mk/linux.mk b/mk/linux.mk
new file mode 100644
index 0000000..ad58f69
--- /dev/null
+++ b/mk/linux.mk
@@ -0,0 +1,6 @@
+LIBEXT = so
+LIBFLAGS = -shared -Wl,-soname,lib$(LIB_NAME).$(LIBEXT).$(LIB_MAJOR)
+LIBMAJOREXT = $(LIBEXT).$(LIB_MAJOR)
+LIBMINOREXT = $(LIBEXT).$(LIB_VERSION)
+
+FIX_INSTALL_NAME = :
diff --git a/mk/macos.mk b/mk/macos.mk
new file mode 100644
index 0000000..7e2d25c
--- /dev/null
+++ b/mk/macos.mk
@@ -0,0 +1,6 @@
+LIBEXT = dylib
+LIBFLAGS = -dynamiclib -Wl,-compatibility_version,$(LIB_MAJOR) -Wl,-current_version,$(LIB_VERSION)
+LIBMAJOREXT = $(LIB_MAJOR).$(LIBEXT)
+LIBMINOREXT = $(LIB_VERSION).$(LIBEXT)
+
+FIX_INSTALL_NAME = install_name_tool -id "$(PREFIX)/lib/libenv.$(LIBMAJOREXT)"
diff --git a/mk/windows.mk b/mk/windows.mk
new file mode 100644
index 0000000..ed5ec8d
--- /dev/null
+++ b/mk/windows.mk
@@ -0,0 +1,6 @@
+LIBEXT = dll
+LIBFLAGS = -shared
+LIBMAJOREXT = $(LIB_MAJOR).$(LIBEXT)
+LIBMINOREXT = $(LIB_VERSION).$(LIBEXT)
+
+FIX_INSTALL_NAME = :
diff --git a/struct_libenv_variable.3 b/struct_libenv_variable.3
new file mode 120000
index 0000000..8bb2806
--- /dev/null
+++ b/struct_libenv_variable.3
@@ -0,0 +1 @@
+libenv_get_complete_list.3 \ No newline at end of file