aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-06-02 07:40:11 +0300
committerSergey Poznyakoff <gray@gnu.org>2019-06-02 08:03:16 +0300
commitcc298a11a131b162f291d6ee27ba1d7598a1b6c4 (patch)
tree4d82a9a5da05fbfdce0c9bf03e605ecf00baa07a /tests
parent1f28935841a69aa8be7eb2e88f580df9c95206d2 (diff)
downloadpies-cc298a11a131b162f291d6ee27ba1d7598a1b6c4.tar.gz
pies-cc298a11a131b162f291d6ee27ba1d7598a1b6c4.tar.bz2
New configuration statement for manipulating the environment.
The "env" statement is now a compound statement. It can contain four substatements: "clear" to clear the environment, "keep" to retain certain variable while clearing it, "set" to set a variable, and "unset" to unset a variable or variables. Both "keep" and "unset" can take globbing pattern as their argument, in which case they affect all variable matching that pattern. The value part in the "set" statement is subject to variable expansion, e.g. set "MANPATH=$MANPATH${MANPATH:+:}/usr/local/man" The support for the old one-line syntax of "env" is retained for backward compatibility. This commit also fixes redirection to a file: new data are appended to the file, instead of overwriting it. * lib/Makefile.am: Add new files. * lib/envop.c: New file. * lib/envop.h: New file. * lib/wildmatch.c: New file. * src/comp.c (component_free): Update. * src/pies.c (argv_free): New function. (parse_legacy_env): New function. (_cb_env): Remove. (cb_env_section_parser): New function. (cb_env_keywords): New keywords for the "env" block statement: clear, keep, set, unset. (component_keywords): New compount statement: env. Old usage retained for backward compatibility. * src/pies.h: Include "envop.h" (component)<env>: Remove. <envop>: New field. * src/prog.h (prog)<env>: New field. * src/progman.c (redirect_to_file): Position to the end of file. (DEBUG_ENVIRON): Remove macro. (debug_environ): New function. (environ_setup): Remove. (prog_sockenv): Use environ_set to modify local copy of environment. (prog_start_prologue): Use environ_create + envop_exec to create and modify the environment. (prog_execute): Set environment to prog-local copy. * tests/.gitignore: Build envtest * tests/Makefile.am: Add new tests. * tests/testsuite.at: Add environment tests. * tests/envop.at: New file. * tests/envtest.c: New file. * tests/env.at: New file. * tests/redirect.at: Check first two lines of the output file.
Diffstat (limited to 'tests')
-rw-r--r--tests/.gitignore1
-rw-r--r--tests/Makefile.am11
-rw-r--r--tests/env.at65
-rw-r--r--tests/envop.at101
-rw-r--r--tests/envtest.c209
-rw-r--r--tests/redirect.at2
-rw-r--r--tests/testsuite.at3
7 files changed, 391 insertions, 1 deletions
diff --git a/tests/.gitignore b/tests/.gitignore
index 93f8f46..276645a 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -1,5 +1,6 @@
atconfig
atlocal
+envtest
package.m4
testsuite
testsuite.dir
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 39899c8..419818b 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -48,6 +48,8 @@ TESTSUITE_AT = \
testsuite.at\
control.at\
cyclic.at\
+ env.at\
+ envop.at\
respawn.at\
redirect.at\
ret-exec.at\
@@ -60,6 +62,15 @@ TESTSUITE_AT = \
TESTSUITE = $(srcdir)/testsuite
M4=m4
+noinst_PROGRAMS = envtest
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/lib\
+ @GRECS_INCLUDES@
+
+LDADD = \
+ ../lib/libpies.a\
+ @GRECS_LDADD@
+
AUTOTEST = $(AUTOM4TE) --language=autotest
$(TESTSUITE): package.m4 $(TESTSUITE_AT)
$(AM_V_GEN)$(AUTOTEST) -I $(srcdir) testsuite.at -o $@.tmp
diff --git a/tests/env.at b/tests/env.at
new file mode 100644
index 0000000..26fe866
--- /dev/null
+++ b/tests/env.at
@@ -0,0 +1,65 @@
+dnl ENVTEST(NAME,KW,ENV,OUT)
+m4_pushdef([ENVTEST],
+[AT_SETUP([$1])
+AT_KEYWORDS([env $2])
+AT_CHECK([
+PIES_XFAIL_CHECK
+PIES_CONTROL_INIT
+cat > envtest.conf <<_EOT
+component envtest {
+ env {
+ $3
+ }
+ command "$abs_builddir/envtest -clone";
+ chdir $PWD;
+ stdout file "$PWD/log";
+ return-code 0 {
+ action disable;
+ exec "piesctl --url unix:///$PWD/pies.ctl shutdown";
+ }
+}
+_EOT
+
+envtest -exec $abs_top_builddir/src/pies --foreground --stderr --config-file control.conf --config-file envtest.conf 2>errlog
+cat log
+],
+[0],
+[$4])
+AT_CLEANUP])
+
+dnl #############################
+dnl Start tests
+dnl #############################
+
+AT_BANNER([Environment statement])
+
+ENVTEST([clear],[clear],[clear yes;],[])
+
+ENVTEST([keep],[keep],[keep "LC_*";],
+[LC_ALL="C"
+LC_CTYPE="C"
+LC_MESSAGES="C"
+LC_NUMERIC="C"
+])
+
+ENVTEST([set],[set],[set "FOO=bar";],
+[FOO="bar"
+HOME="/home/user"
+LC_ALL="C"
+LC_CTYPE="C"
+LC_MESSAGES="C"
+LC_NUMERIC="C"
+LOGIN="user"
+PATH="/usr/local/bin:/usr/bin:/bin"
+PIES_INSTANCE="pies"
+PWD="/home"
+USER="user"
+])
+
+ENVTEST([unset],[unset],[unset "LC_*"; unset PWD;],
+[HOME="/home/user"
+LOGIN="user"
+PATH="/usr/local/bin:/usr/bin:/bin"
+PIES_INSTANCE="pies"
+USER="user"
+])
diff --git a/tests/envop.at b/tests/envop.at
new file mode 100644
index 0000000..6f634fb
--- /dev/null
+++ b/tests/envop.at
@@ -0,0 +1,101 @@
+# ENVTEST(name,kw,args,output)
+m4_pushdef([ENVTEST],
+[AT_SETUP([$1])
+AT_KEYWORDS([envop $2])
+AT_CHECK([envtest $3],
+[0],
+[$4])
+AT_CLEANUP
+])
+dnl #############################
+dnl Start tests
+dnl #############################
+
+AT_BANNER([Environment modification framework])
+
+ENVTEST([default environment],[defenv],[],
+[HOME="/home/user"
+LC_ALL="C"
+LC_CTYPE="C"
+LC_MESSAGES="C"
+LC_NUMERIC="C"
+LOGIN="user"
+PATH="/usr/local/bin:/usr/bin:/bin"
+PWD="/home"
+USER="user"
+])
+
+ENVTEST([clear],[clear],[-clear])
+
+ENVTEST([keep name],[keep],[-clear -keep HOME USER],
+[HOME="/home/user"
+USER="user"
+])
+
+ENVTEST([keep name=value],[keep],[-clear -keep USER=user],
+[USER="user"
+])
+
+ENVTEST([keep name=value (mismatch)],[keep],[-clear -keep USER=gray])
+
+ENVTEST([keep wildcard],[keep],[-clear -keep 'LC_*'],
+[LC_ALL="C"
+LC_CTYPE="C"
+LC_MESSAGES="C"
+LC_NUMERIC="C"
+])
+
+ENVTEST([keep wildcard (2)],[keep],[-clear -keep 'LC_*A*'],
+[LC_ALL="C"
+LC_MESSAGES="C"
+])
+
+ENVTEST([keep wildcard (mismatch)],[keep],[-clear -keep 'LC_*A*R'])
+
+ENVTEST([set],[set],[-set FOO=bar BAR=bar],
+[BAR="bar"
+FOO="bar"
+HOME="/home/user"
+LC_ALL="C"
+LC_CTYPE="C"
+LC_MESSAGES="C"
+LC_NUMERIC="C"
+LOGIN="user"
+PATH="/usr/local/bin:/usr/bin:/bin"
+PWD="/home"
+USER="user"
+])
+
+ENVTEST([set (variable expansion)],[set],[-set 'PATH=${PATH}${PATH:+:}$HOME'],
+[HOME="/home/user"
+LC_ALL="C"
+LC_CTYPE="C"
+LC_MESSAGES="C"
+LC_NUMERIC="C"
+LOGIN="user"
+PATH="/usr/local/bin:/usr/bin:/bin:/home/user"
+PWD="/home"
+USER="user"
+])
+
+ENVTEST([unset name],[unset],[-unset HOME],
+[LC_ALL="C"
+LC_CTYPE="C"
+LC_MESSAGES="C"
+LC_NUMERIC="C"
+LOGIN="user"
+PATH="/usr/local/bin:/usr/bin:/bin"
+PWD="/home"
+USER="user"
+])
+
+ENVTEST([unset wildcard],[unset],[-unset 'LC_*'],
+[HOME="/home/user"
+LOGIN="user"
+PATH="/usr/local/bin:/usr/bin:/bin"
+PWD="/home"
+USER="user"
+])
+
+m4_popdef([ENVTEST])
+
diff --git a/tests/envtest.c b/tests/envtest.c
new file mode 100644
index 0000000..d6b5650
--- /dev/null
+++ b/tests/envtest.c
@@ -0,0 +1,209 @@
+/* Environment test program for GNU Pies.
+ Copyright (C) 2019 Sergey Poznyakoff
+
+ GNU Pies is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GNU Pies is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <ctype.h>
+#include <envop.h>
+#include <wordsplit.h>
+
+static int
+envcmp (void const *a, void const *b)
+{
+ char const *as = *(char const **)a;
+ char const *bs = *(char const **)b;
+ int c;
+
+ while (*as && *bs)
+ {
+ c = *as - *bs;
+ if (c || *as == '=' || *bs == '=')
+ break;
+ as++;
+ bs++;
+ }
+ return c;
+}
+
+static void
+sortenv (char **env)
+{
+ size_t n;
+ for (n = 0; env[n]; n++)
+ ;
+ qsort (env, n, sizeof (env[0]), envcmp);
+}
+
+static void
+printenv (char **env)
+{
+ size_t i;
+ for (i = 0; env[i]; i++)
+ {
+ char *p = env[i];
+ while (*p)
+ {
+ fputc (*p, stdout);
+ if (*p++ == '=')
+ break;
+ }
+ if (*p)
+ {
+ int c;
+ fputc ('"', stdout);
+ while ((c = *p++) != 0)
+ {
+ int c1;
+ if (isascii (c) && isprint (c) && c != '\\' && c != '"')
+ fputc (c, stdout);
+ else if ((c1 = wordsplit_c_quote_char (c)))
+ {
+ fputc ('\\', stdout);
+ fputc (c1, stdout);
+ }
+ }
+ fputc ('"', stdout);
+ }
+ fputc ('\n', stdout);
+ }
+}
+
+char *defenv[] = {
+ "PATH=/usr/local/bin:/usr/bin:/bin",
+ "HOME=/home/user",
+ "USER=user",
+ "LOGIN=user",
+ "PWD=/home",
+ "LC_ALL=C",
+ "LC_CTYPE=C",
+ "LC_MESSAGES=C",
+ "LC_NUMERIC=C",
+ NULL
+};
+
+extern char **environ;
+
+int
+main (int argc, char **argv)
+{
+ envop_t *envop = NULL;
+ int opcode = envop_set;
+ environ_t *env = NULL;
+
+ if (argc > 1)
+ {
+ if (strcmp (argv[1], "-clone") == 0)
+ {
+ env = environ_create (environ);
+ argc--;
+ argv++;
+ }
+ else if (strcmp (argv[1], "-null") == 0)
+ {
+ env = environ_create (NULL);
+ argc--;
+ argv++;
+ }
+ }
+
+ if (!env)
+ env = environ_create (defenv);
+
+ if (!env)
+ {
+ perror ("environ_create");
+ abort ();
+ }
+
+ while (--argc)
+ {
+ char *a = *++argv;
+
+ if (strcmp (a, "-set") == 0)
+ opcode = envop_set;
+ else if (strcmp (a, "-unset") == 0)
+ opcode = envop_unset;
+ else if (strcmp (a, "-keep") == 0)
+ opcode = envop_keep;
+ else if (strcmp (a, "-clear") == 0)
+ {
+ int rc = envop_entry_add (&envop, envop_clear, NULL, NULL);
+ if (rc)
+ {
+ perror ("envop_entry_add");
+ return 1;
+ }
+ }
+ else if (strcmp (a, "-exec") == 0)
+ {
+ --argc;
+ ++argv;
+ if (argc == 0)
+ {
+ fprintf (stderr, "program name required after -exec\n");
+ return 1;
+ }
+ break;
+ }
+ else if (a[0] == '-')
+ {
+ fprintf (stderr, "unrecognized option: %s\n", a);
+ return 1;
+ }
+ else
+ {
+ int rc;
+ char *p = strchr (a, '=');
+
+ if (p)
+ *p++ = 0;
+ rc = envop_entry_add (&envop, opcode, a, p);
+
+ if (rc)
+ {
+ perror ("envop_entry_add");
+ return 1;
+ }
+ }
+ }
+
+ if (envop_exec (envop, env))
+ {
+ perror ("envop_exec");
+ return 1;
+ }
+
+ if (argc)
+ {
+ environ = environ_ptr (env);
+ execvp (argv[0], argv);
+ perror ("execvp");
+ abort ();
+ }
+
+ sortenv (env->env_base);
+ printenv (env->env_base);
+ return 0;
+}
+
+
+
diff --git a/tests/redirect.at b/tests/redirect.at
index 3a8cca7..7860736 100644
--- a/tests/redirect.at
+++ b/tests/redirect.at
@@ -50,7 +50,7 @@ done
PIES_STOP
-cat $outfile
+head -2 $outfile
],
[0],
[respawn: start
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 28d1f9d..e340a2b 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -68,3 +68,6 @@ m4_include([ret-notify.at])
m4_include([startup.at])
m4_include([shutdown.at])
m4_include([shell.at])
+
+m4_include([envop.at])
+m4_include([env.at]) \ No newline at end of file

Return to:

Send suggestions and report system problems to the System administrator.