diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-12-01 23:11:39 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-12-02 08:11:26 +0200 |
commit | c0f4c3b99bb3364fe3f840b1ecb44af2eeba097b (patch) | |
tree | 374bc9fe1a9802d97f027b56ddf9a1f59268fb4e | |
parent | c26297063aa2dad0fecd28791a47a8bffcfc9925 (diff) | |
download | pies-c0f4c3b99bb3364fe3f840b1ecb44af2eeba097b.tar.gz pies-c0f4c3b99bb3364fe3f840b1ecb44af2eeba097b.tar.bz2 |
New component flag: expandenv
* NEWS: Update.
* doc/pies.texi: Document the expandenv flag.
* src/comp.c (component_finish): Warn if both "shell" and "expandenv"
are used together.
Expand command to argc/argv only unless the CF_EXPANDENV flag is given.
* src/pies.c (str_to_cf): New flag: expandenv
* src/pies.h (CF_EXPANDENV): New define.
* src/prog.h (struct prog): New member: argv.
* src/progman.c (destroy_prog): Free argv.
(prog_start_prologue): Expand the command line taking into account
the current environment if CF_EXPANDENV flag is given. Otherwise,
copy the component argv to the prog.
(prog_execute): Use prog->v.p.argv
* tests/Makefile.am: Add expandenv.at
* tests/testsuite.at: Likewise.
* tests/expandenv.at: New file.
-rw-r--r-- | NEWS | 13 | ||||
-rw-r--r-- | doc/pies.texi | 68 | ||||
-rw-r--r-- | src/comp.c | 10 | ||||
-rw-r--r-- | src/pies.c | 1 | ||||
-rw-r--r-- | src/pies.h | 2 | ||||
-rw-r--r-- | src/prog.h | 1 | ||||
-rw-r--r-- | src/progman.c | 33 | ||||
-rw-r--r-- | tests/Makefile.am | 1 | ||||
-rw-r--r-- | tests/expandenv.at | 50 | ||||
-rw-r--r-- | tests/testsuite.at | 3 |
10 files changed, 159 insertions, 23 deletions
@@ -1,4 +1,4 @@ -GNU Pies NEWS -- history of user-visible changes. 2020-10-18 +GNU Pies NEWS -- history of user-visible changes. 2020-12-01 See the end of file for copying conditions. Please send Pies bug reports to <bug-pies@gnu.org> or @@ -17,6 +17,17 @@ properly. * Fix cyclic dependency detection +* New component flag: expandenv + +The "expandenv" flag instructs pies to parse the command line +and to expand any references to environment variables within it +as the Bourne shell would have done it. This allows for expanding +the environment variables without the overhead of actually running +the shell. + +This flag is incompatible with the "shell" flag. When both are used, +the preference is given to "shell" and a warning message to that +effect is issued. Version 1.4, 2019-07-02 diff --git a/doc/pies.texi b/doc/pies.texi index b2c9716..7a21434 100644 --- a/doc/pies.texi +++ b/doc/pies.texi @@ -124,6 +124,7 @@ Component Statement * Component Privileges:: * Resources:: * Environment:: +* Early Environment Expansion:: * Actions Before Startup:: * Exit Actions:: * Output Redirectors:: @@ -836,22 +837,19 @@ any other processes. @end table @end deffn -@deffn {Config: component} program @var{name} -Full file name of the component binary. This binary will be executed -(via @command{/bin/sh -c}) each time @command{pies} decides it needs -to start the component. - -To supply command line arguments, use @code{command} statement. -@end deffn - @deffn {Config: component} command @var{string} -Command line for the program. The argument should be just as -arguments normally are, starting with the name of the program. The -latter may be different from the one specified to @code{program} -statement. Its value will be available to the program as -@code{argv[0]}. +Command line to run. The argument is the full command line. The +first word (in the shell sense) in @var{string} is the name of the +program to invoke. @end deffn +@deffn {Config: component} program @var{name} +Full file name of the program to run. When supplied, @command{pies} +will execute the program @var{name} instead of the first word in the +@code{command} statement. The latter, however, will be passed to +the running program as @code{argv[0]}. +@end deffn + @anchor{flags} @deffn {Config: component} flags (@var{flag-list}) Define flags for this component. The @var{flag-list} is a @@ -891,6 +889,13 @@ component X @{ @} @end example +@kwindex expandenv +@item expandenv +Expand environment variables in the @samp{command} statement prior to +running it. When used together with the @samp{shell} flag, this flag +produces a warning and has no effect. @xref{Early Environment +Expansion}, for a detailed discussion. + @kwindex wait @item wait This flag is valid only for @samp{inetd} components. It has the same @@ -940,6 +945,7 @@ substatements. * Component Privileges:: * Resources:: * Environment:: +* Early Environment Expansion:: * Actions Before Startup:: * Exit Actions:: * Output Redirectors:: @@ -1293,6 +1299,42 @@ env @{ @end table @end deffn +@node Early Environment Expansion +@subsection Early Environment Expansion + + By default any references to environment variables encountered in +the @code{command} statement are not expanded. If you need to expand +them, there are two @dfn{flags} (@pxref{flags}) at your disposal: +@samp{shell} and @samp{expandenv}. + +The @samp{shell} flag instructs @command{pies} to pass the command +line specified by the the @code{command} statement as the argument to +the @samp{/bin/sh -c} command (or another shell, if specified by the +@samp{program} statement). This naturaly causes all references to the +environment variables to be expanded, as in shell. The overhead is +that two processes are run instead of the one: first the shell and +second the command itself, being run as its child. This overhead +can be eliminated by using the @code{exec} statement before the +command, to instruct the shell to replace itself with the command +without creating a new process. + + Another way to expand environment variables in the command line is by +specifying the @samp{expandenv} flag. This flag instructs +@command{pies} to expand any variable references the same way that the +Bourne shell would expand them, but without actually invoking the +shell. + + Which way to choose depends on he command. If it is a shell +built-in, a pipe or a complex shell command, use @samp{flags shell}. +Otherwise, you'd be better off using @samp{flags expandenv}. + + When the two flags are used together, the preference is given to +@samp{shell}, and a warning message to that effect is issued. + + Also, please note, that whichever option you chose the environment +variables available for expansion are those inherited by the parent +shell and modified by the @code{env} statement (@pxref{Environment}). + @node Actions Before Startup @subsection Actions Before Startup @@ -724,6 +724,14 @@ component_finish (struct component *comp, grecs_locus_t *locus) if (comp->flags & CF_SHELL) { + if (comp->flags & CF_EXPANDENV) + { + grecs_warning (locus, 0, + "%s", + _("flags \"shell\" and \"expandenv\" used together: " + "ignoring \"expandenv\"")); + comp->flags &= ~CF_EXPANDENV; + } comp->argc = 3; comp->argv = grecs_calloc (comp->argc + 1, sizeof (comp->argv[0])); comp->argv[0] = grecs_strdup (comp->program ? comp->program : "/bin/sh"); @@ -731,7 +739,7 @@ component_finish (struct component *comp, grecs_locus_t *locus) comp->argv[2] = grecs_strdup (comp->command); comp->argv[3] = NULL; } - else if (comp->command) + else if (comp->command && !(comp->flags & CF_EXPANDENV)) { struct wordsplit ws; if (wordsplit (comp->command, &ws, WRDSF_DEFFLAGS)) @@ -1143,6 +1143,7 @@ str_to_cf (const char *string, int *flags) { "siggroup", CF_SIGGROUP }, { "nullinput", CF_NULLINPUT }, { "shell", CF_SHELL }, + { "expandenv", CF_EXPANDENV }, { NULL } }; @@ -209,6 +209,8 @@ enum pies_comp_mode #define CF_SIGGROUP 0x100 /* Send signals to the process group */ #define CF_NULLINPUT 0x200 /* Provide null input stream */ #define CF_SHELL 0x400 /* Invoke via sh -c */ +#define CF_EXPANDENV 0x800 /* Expand environment variables in the command + line */ #define CF_REMOVE 0xf000 /* Marked for removal */ @@ -53,6 +53,7 @@ struct prog struct { struct component *comp; + char **argv; /* Actual command line (NULL-terminated) */ int socket; struct prog *redir[2]; /* Pointers to redirectors */ time_t timestamp; /* Time of last startup */ diff --git a/src/progman.c b/src/progman.c index 2a073af..1cd5f9d 100644 --- a/src/progman.c +++ b/src/progman.c @@ -156,6 +156,8 @@ destroy_prog (struct prog **pp) switch (p->type) { case TYPE_COMPONENT: + if (p->v.p.comp->flags & CF_EXPANDENV) + argv_free (p->v.p.argv); component_ref_decr (p->v.p.comp); if (p->v.p.status == status_listener && p->v.p.socket != -1) deregister_socket (p->v.p.socket); @@ -840,14 +842,31 @@ prog_start_prologue (struct prog *prog) prog->v.p.comp->limits ? prog->v.p.comp->limits : pies_limits); - if (debug_level >= 1) + if (prog->v.p.comp->flags & CF_EXPANDENV) { - int i; - struct component *comp = prog->v.p.comp; + struct wordsplit ws; + size_t argc; + ws.ws_env = (const char **) environ_ptr (prog->v.p.env); + if (wordsplit (prog->v.p.comp->command, &ws, + WRDSF_QUOTE | WRDSF_SQUEEZE_DELIMS | WRDSF_NOCMD | WRDSF_ENV)) + { + logmsg (LOG_ERR, _("%s: can't split command line: %s"), + prog_tag (prog), wordsplit_strerror (&ws)); + _exit (127); + } + wordsplit_get_words (&ws, &argc, &prog->v.p.argv); + wordsplit_free (&ws); + } + else + prog->v.p.argv = prog->v.p.comp->argv; + + if (debug_level >= 1 && prog->v.p.argv) + { + int i; logmsg_printf (LOG_DEBUG, "executing"); - for (i = 0; i < comp->argc; i++) - logmsg_printf (LOG_DEBUG, " %s", quotearg (comp->argv[i])); + for (i = 0; prog->v.p.argv[i]; i++) + logmsg_printf (LOG_DEBUG, " %s", quotearg (prog->v.p.argv[i])); logmsg_printf (LOG_DEBUG, "\n"); } } @@ -865,8 +884,8 @@ prog_execute (struct prog *prog) } execvp (prog->v.p.comp->program ? - prog->v.p.comp->program : prog->v.p.comp->argv[0], - prog->v.p.comp->argv); + prog->v.p.comp->program : prog->v.p.argv[0], + prog->v.p.argv); openlog (log_tag, LOG_PID, prog->v.p.comp->facility); syslog (LOG_CRIT, _("cannot start `%s': %s"), prog_tag (prog), strerror (errno)); diff --git a/tests/Makefile.am b/tests/Makefile.am index bfdc692..6a9a0d8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -55,6 +55,7 @@ TESTSUITE_AT = \ cyclic.at\ env.at\ envop.at\ + expandenv.at\ inet.at\ maxinst.at\ passfd.at\ diff --git a/tests/expandenv.at b/tests/expandenv.at new file mode 100644 index 0000000..5518472 --- /dev/null +++ b/tests/expandenv.at @@ -0,0 +1,50 @@ +# This file is part of GNU pies testsuite. -*- Autotest -*- +# Copyright (C) 2016-2020 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/>. + +AT_SETUP([flags expandenv]) + +AT_CHECK([ +PIES_XFAIL_CHECK +PIES_CONTROL_INIT +statefile=$PWD/state +cat > pies.conf <<EOT +component test { + mode respawn; + flags expandenv; + command "\$auxdir/respawn \$statefile 3"; + chdir "$PWD"; + return-code 1 { + action disable; + exec "piesctl --url unix:///$PWD/pies.ctl --no-netrc shutdown"; + } +} +EOT + +export auxdir +export statefile + +set -e +to 5 \ + pies --foreground --stderr \ + --config-file control.conf --config-file pies.conf --debug 4 2>errlog + +cat state +], +[0], +[3 +]) + +AT_CLEANUP diff --git a/tests/testsuite.at b/tests/testsuite.at index eab643d..277cf8b 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -1,4 +1,4 @@ -# This file is part of GNU pies testsuite. -*- Autotest -*- +# This file is part of GNU pies testsuite. -*- autotest -*- # Copyright (C) 2016-2020 Sergey Poznyakoff # # GNU pies is free software; you can redistribute it and/or modify @@ -69,6 +69,7 @@ m4_include([ret-notify.at]) m4_include([startup.at]) m4_include([shutdown.at]) m4_include([shell.at]) +m4_include([expandenv.at]) m4_include([inet.at]) m4_include([maxinst.at]) m4_include([builtin.at]) |