summaryrefslogtreecommitdiffabout
path: root/tests
authorSergey Poznyakoff <gray@gnu.org>2019-06-02 04:40:11 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2019-06-02 05:03:16 (GMT)
commitcc298a11a131b162f291d6ee27ba1d7598a1b6c4 (patch) (unidiff)
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') (more/less context) (ignore whitespace changes)
-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 @@
1atconfig 1atconfig
2atlocal 2atlocal
3envtest
3package.m4 4package.m4
4testsuite 5testsuite
5testsuite.dir 6testsuite.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 = \
48 testsuite.at\ 48 testsuite.at\
49 control.at\ 49 control.at\
50 cyclic.at\ 50 cyclic.at\
51 env.at\
52 envop.at\
51 respawn.at\ 53 respawn.at\
52 redirect.at\ 54 redirect.at\
53 ret-exec.at\ 55 ret-exec.at\
@@ -60,6 +62,15 @@ TESTSUITE_AT = \
60TESTSUITE = $(srcdir)/testsuite 62TESTSUITE = $(srcdir)/testsuite
61M4=m4 63M4=m4
62 64
65noinst_PROGRAMS = envtest
66AM_CPPFLAGS = \
67 -I$(top_srcdir)/lib\
68 @GRECS_INCLUDES@
69
70LDADD = \
71 ../lib/libpies.a\
72 @GRECS_LDADD@
73
63AUTOTEST = $(AUTOM4TE) --language=autotest 74AUTOTEST = $(AUTOM4TE) --language=autotest
64$(TESTSUITE): package.m4 $(TESTSUITE_AT) 75$(TESTSUITE): package.m4 $(TESTSUITE_AT)
65 $(AM_V_GEN)$(AUTOTEST) -I $(srcdir) testsuite.at -o $@.tmp 76 $(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
--- a/dev/null
+++ b/tests/env.at
@@ -0,0 +1,65 @@
1dnl ENVTEST(NAME,KW,ENV,OUT)
2m4_pushdef([ENVTEST],
3[AT_SETUP([$1])
4AT_KEYWORDS([env $2])
5AT_CHECK([
6PIES_XFAIL_CHECK
7PIES_CONTROL_INIT
8cat > envtest.conf <<_EOT
9component envtest {
10 env {
11 $3
12 }
13 command "$abs_builddir/envtest -clone";
14 chdir $PWD;
15 stdout file "$PWD/log";
16 return-code 0 {
17 action disable;
18 exec "piesctl --url unix:///$PWD/pies.ctl shutdown";
19 }
20}
21_EOT
22
23envtest -exec $abs_top_builddir/src/pies --foreground --stderr --config-file control.conf --config-file envtest.conf 2>errlog
24cat log
25],
26[0],
27[$4])
28AT_CLEANUP])
29
30dnl #############################
31dnl Start tests
32dnl #############################
33
34AT_BANNER([Environment statement])
35
36ENVTEST([clear],[clear],[clear yes;],[])
37
38ENVTEST([keep],[keep],[keep "LC_*";],
39[LC_ALL="C"
40LC_CTYPE="C"
41LC_MESSAGES="C"
42LC_NUMERIC="C"
43])
44
45ENVTEST([set],[set],[set "FOO=bar";],
46[FOO="bar"
47HOME="/home/user"
48LC_ALL="C"
49LC_CTYPE="C"
50LC_MESSAGES="C"
51LC_NUMERIC="C"
52LOGIN="user"
53PATH="/usr/local/bin:/usr/bin:/bin"
54PIES_INSTANCE="pies"
55PWD="/home"
56USER="user"
57])
58
59ENVTEST([unset],[unset],[unset "LC_*"; unset PWD;],
60[HOME="/home/user"
61LOGIN="user"
62PATH="/usr/local/bin:/usr/bin:/bin"
63PIES_INSTANCE="pies"
64USER="user"
65])
diff --git a/tests/envop.at b/tests/envop.at
new file mode 100644
index 0000000..6f634fb
--- a/dev/null
+++ b/tests/envop.at
@@ -0,0 +1,101 @@
1# ENVTEST(name,kw,args,output)
2m4_pushdef([ENVTEST],
3[AT_SETUP([$1])
4AT_KEYWORDS([envop $2])
5AT_CHECK([envtest $3],
6[0],
7[$4])
8AT_CLEANUP
9])
10dnl #############################
11dnl Start tests
12dnl #############################
13
14AT_BANNER([Environment modification framework])
15
16ENVTEST([default environment],[defenv],[],
17[HOME="/home/user"
18LC_ALL="C"
19LC_CTYPE="C"
20LC_MESSAGES="C"
21LC_NUMERIC="C"
22LOGIN="user"
23PATH="/usr/local/bin:/usr/bin:/bin"
24PWD="/home"
25USER="user"
26])
27
28ENVTEST([clear],[clear],[-clear])
29
30ENVTEST([keep name],[keep],[-clear -keep HOME USER],
31[HOME="/home/user"
32USER="user"
33])
34
35ENVTEST([keep name=value],[keep],[-clear -keep USER=user],
36[USER="user"
37])
38
39ENVTEST([keep name=value (mismatch)],[keep],[-clear -keep USER=gray])
40
41ENVTEST([keep wildcard],[keep],[-clear -keep 'LC_*'],
42[LC_ALL="C"
43LC_CTYPE="C"
44LC_MESSAGES="C"
45LC_NUMERIC="C"
46])
47
48ENVTEST([keep wildcard (2)],[keep],[-clear -keep 'LC_*A*'],
49[LC_ALL="C"
50LC_MESSAGES="C"
51])
52
53ENVTEST([keep wildcard (mismatch)],[keep],[-clear -keep 'LC_*A*R'])
54
55ENVTEST([set],[set],[-set FOO=bar BAR=bar],
56[BAR="bar"
57FOO="bar"
58HOME="/home/user"
59LC_ALL="C"
60LC_CTYPE="C"
61LC_MESSAGES="C"
62LC_NUMERIC="C"
63LOGIN="user"
64PATH="/usr/local/bin:/usr/bin:/bin"
65PWD="/home"
66USER="user"
67])
68
69ENVTEST([set (variable expansion)],[set],[-set 'PATH=${PATH}${PATH:+:}$HOME'],
70[HOME="/home/user"
71LC_ALL="C"
72LC_CTYPE="C"
73LC_MESSAGES="C"
74LC_NUMERIC="C"
75LOGIN="user"
76PATH="/usr/local/bin:/usr/bin:/bin:/home/user"
77PWD="/home"
78USER="user"
79])
80
81ENVTEST([unset name],[unset],[-unset HOME],
82[LC_ALL="C"
83LC_CTYPE="C"
84LC_MESSAGES="C"
85LC_NUMERIC="C"
86LOGIN="user"
87PATH="/usr/local/bin:/usr/bin:/bin"
88PWD="/home"
89USER="user"
90])
91
92ENVTEST([unset wildcard],[unset],[-unset 'LC_*'],
93[HOME="/home/user"
94LOGIN="user"
95PATH="/usr/local/bin:/usr/bin:/bin"
96PWD="/home"
97USER="user"
98])
99
100m4_popdef([ENVTEST])
101
diff --git a/tests/envtest.c b/tests/envtest.c
new file mode 100644
index 0000000..d6b5650
--- a/dev/null
+++ b/tests/envtest.c
@@ -0,0 +1,209 @@
1/* Environment test program for GNU Pies.
2 Copyright (C) 2019 Sergey Poznyakoff
3
4 GNU Pies is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Pies is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17#ifdef HAVE_CONFIG_H
18# include <config.h>
19#endif
20#include <stdlib.h>
21#include <stdio.h>
22#include <string.h>
23#include <unistd.h>
24#include <errno.h>
25#include <ctype.h>
26#include <envop.h>
27#include <wordsplit.h>
28
29static int
30envcmp (void const *a, void const *b)
31{
32 char const *as = *(char const **)a;
33 char const *bs = *(char const **)b;
34 int c;
35
36 while (*as && *bs)
37 {
38 c = *as - *bs;
39 if (c || *as == '=' || *bs == '=')
40 break;
41 as++;
42 bs++;
43 }
44 return c;
45}
46
47static void
48sortenv (char **env)
49{
50 size_t n;
51 for (n = 0; env[n]; n++)
52 ;
53 qsort (env, n, sizeof (env[0]), envcmp);
54}
55
56static void
57printenv (char **env)
58{
59 size_t i;
60 for (i = 0; env[i]; i++)
61 {
62 char *p = env[i];
63 while (*p)
64 {
65 fputc (*p, stdout);
66 if (*p++ == '=')
67 break;
68 }
69 if (*p)
70 {
71 int c;
72 fputc ('"', stdout);
73 while ((c = *p++) != 0)
74 {
75 int c1;
76 if (isascii (c) && isprint (c) && c != '\\' && c != '"')
77 fputc (c, stdout);
78 else if ((c1 = wordsplit_c_quote_char (c)))
79 {
80 fputc ('\\', stdout);
81 fputc (c1, stdout);
82 }
83 }
84 fputc ('"', stdout);
85 }
86 fputc ('\n', stdout);
87 }
88}
89
90char *defenv[] = {
91 "PATH=/usr/local/bin:/usr/bin:/bin",
92 "HOME=/home/user",
93 "USER=user",
94 "LOGIN=user",
95 "PWD=/home",
96 "LC_ALL=C",
97 "LC_CTYPE=C",
98 "LC_MESSAGES=C",
99 "LC_NUMERIC=C",
100 NULL
101};
102
103extern char **environ;
104
105int
106main (int argc, char **argv)
107{
108 envop_t *envop = NULL;
109 int opcode = envop_set;
110 environ_t *env = NULL;
111
112 if (argc > 1)
113 {
114 if (strcmp (argv[1], "-clone") == 0)
115 {
116 env = environ_create (environ);
117 argc--;
118 argv++;
119 }
120 else if (strcmp (argv[1], "-null") == 0)
121 {
122 env = environ_create (NULL);
123 argc--;
124 argv++;
125 }
126 }
127
128 if (!env)
129 env = environ_create (defenv);
130
131 if (!env)
132 {
133 perror ("environ_create");
134 abort ();
135 }
136
137 while (--argc)
138 {
139 char *a = *++argv;
140
141 if (strcmp (a, "-set") == 0)
142 opcode = envop_set;
143 else if (strcmp (a, "-unset") == 0)
144 opcode = envop_unset;
145 else if (strcmp (a, "-keep") == 0)
146 opcode = envop_keep;
147 else if (strcmp (a, "-clear") == 0)
148 {
149 int rc = envop_entry_add (&envop, envop_clear, NULL, NULL);
150 if (rc)
151 {
152 perror ("envop_entry_add");
153 return 1;
154 }
155 }
156 else if (strcmp (a, "-exec") == 0)
157 {
158 --argc;
159 ++argv;
160 if (argc == 0)
161 {
162 fprintf (stderr, "program name required after -exec\n");
163 return 1;
164 }
165 break;
166 }
167 else if (a[0] == '-')
168 {
169 fprintf (stderr, "unrecognized option: %s\n", a);
170 return 1;
171 }
172 else
173 {
174 int rc;
175 char *p = strchr (a, '=');
176
177 if (p)
178 *p++ = 0;
179 rc = envop_entry_add (&envop, opcode, a, p);
180
181 if (rc)
182 {
183 perror ("envop_entry_add");
184 return 1;
185 }
186 }
187 }
188
189 if (envop_exec (envop, env))
190 {
191 perror ("envop_exec");
192 return 1;
193 }
194
195 if (argc)
196 {
197 environ = environ_ptr (env);
198 execvp (argv[0], argv);
199 perror ("execvp");
200 abort ();
201 }
202
203 sortenv (env->env_base);
204 printenv (env->env_base);
205 return 0;
206}
207
208
209
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
50 50
51PIES_STOP 51PIES_STOP
52 52
53cat $outfile 53head -2 $outfile
54], 54],
55[0], 55[0],
56[respawn: start 56[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])
68m4_include([startup.at]) 68m4_include([startup.at])
69m4_include([shutdown.at]) 69m4_include([shutdown.at])
70m4_include([shell.at]) 70m4_include([shell.at])
71
72m4_include([envop.at])
73m4_include([env.at]) \ No newline at end of file

Return to:

Send suggestions and report system problems to the System administrator.