aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS22
-rw-r--r--doc/pies.texi21
-rw-r--r--src/comp.c24
-rw-r--r--src/pies.c48
-rw-r--r--src/pies.h5
-rw-r--r--tests/Makefile.am1
-rwxr-xr-xtests/aux/respawn2
-rw-r--r--tests/respawn.at2
-rw-r--r--tests/shell.at58
-rw-r--r--tests/testsuite.at1
10 files changed, 137 insertions, 47 deletions
diff --git a/NEWS b/NEWS
index 0840055..f34a6f0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,7 +1,7 @@
-GNU Pies NEWS -- history of user-visible changes. 2019-05-28
+GNU Pies NEWS -- history of user-visible changes. 2019-05-31
See the end of file for copying conditions.
Please send Pies bug reports to <bug-pies@gnu.org> or
<bug-pies@gnu.org.ua>
Version 1.3.90 (git)
@@ -22,14 +22,34 @@ all other components have been terminated.
Any number of startup or shutdwon components can be defined in the
configuration file. Such multiple components are run simultaneously,
unless required otherwise by their "prerequisites" and "dependents"
statements.
+* New component flag: shell
+
+The 'shell' flag instructs pies to run the component via "/bin/sh -c
+$command". Use it if the command should undergo variable expansion,
+contains redirections, pipes, etc. E.g.
+
+ component X {
+ flags shell;
+ command "if [ -n "$X" ]; then foo; else bar; fi"
+ }
+
* Improved cyclic dependency diagnostics
+* Fix a bug in 'env' statement
+
+Previous versions applied unnecessary word splitting if given a
+single argument. This is now fixed, so that e.g. the following
+statement is processed correctly and defines a single variable
+X to have the value "foo bar":
+
+ env "X=foo bar"
+
Version 1.3, 2016-10-01
* SysV-style Init
GNU Pies can now be used as init process daemon - the first process
diff --git a/doc/pies.texi b/doc/pies.texi
index 012ac88..1a798e1 100644
--- a/doc/pies.texi
+++ b/doc/pies.texi
@@ -173,13 +173,17 @@ starts and controls execution of external programs. In this document
these programs will be referred to as @dfn{components}. Each
component is a stand-alone program, which is executed in the
foreground.
Upon startup, @command{pies} reads the list of components
from its configuration file, starts them, and remains in the
-background, controlling their execution.
+background, controlling their execution. Each component is
+defined by the name of the external program to be run and its
+arguments (command line). The program is normally run directly
+(via @code{exec}), but you can instruct @command{pies} to run
+it via @code{sh -c} as well.
The standard output and standard error streams of a component can be
redirected to a file or to an arbitrary @command{syslog} channel.
The way of handling each component, and in particular the action to
be taken upon its termination is determined by the component's @dfn{mode}.
@@ -867,12 +871,27 @@ their standard input to be open (e.g.@: @command{pppd nodetach}).
@kwindex precious
@item precious
Mark this component as @dfn{precious}. Precious components are never
disabled by @command{pies}, even if they respawn too fast.
+@kwindex shell
+@item shell
+Run command as @code{/bin/sh -c "$command"}. Use this flag if command
+contains shell-specific features, such as I/O redirections, pipes,
+variables or the like. You can change the shell program using the
+@code{program} statement. For example, to use Korn shell:
+
+@example
+component X @{
+ flags shell;
+ program "/bin/ksh";
+ command "myprog $HOME";
+@}
+@end example
+
@kwindex wait
@item wait
This flag is valid only for @samp{inetd} components. It has the same
meaning as @samp{wait} in @file{inetd.conf} file, i.e. it tells
@command{pies} to wait for the server program to
return. @xref{inetd.conf, wait}.
diff --git a/src/comp.c b/src/comp.c
index 25f2657..499dfe5 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -168,12 +168,13 @@ component_free (struct component *comp)
{
size_t i;
component_unlink (comp);
free (comp->tag);
free (comp->program);
+ free (comp->command);
if (comp->argv)
{
for (i = 0; i < comp->argc; i++)
free (comp->argv[i]);
free (comp->argv);
}
@@ -744,12 +745,35 @@ component_verify (struct component *comp, grecs_locus_t *locus)
#undef COMPERR
}
void
component_finish (struct component *comp, grecs_locus_t *locus)
{
+ if (comp->flags & CF_SHELL)
+ {
+ 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");
+ comp->argv[1] = grecs_strdup ("-c");
+ comp->argv[2] = grecs_strdup (comp->command);
+ comp->argv[3] = NULL;
+ }
+ else
+ {
+ struct wordsplit ws;
+ if (wordsplit (comp->command, &ws, WRDSF_DEFFLAGS))
+ {
+ grecs_error (locus, 0, "wordsplit: %s",
+ wordsplit_strerror (&ws));
+ component_free (comp);
+ return;
+ }
+ wordsplit_get_words (&ws, &comp->argc, &comp->argv);
+ wordsplit_free (&ws);
+ }
+
if (comp->prereq)
comp->prereq->cmp = list_str_cmp;
if (comp->depend)
comp->depend->cmp = list_str_cmp;
if (comp->privs.groups)
comp->privs.groups->cmp = list_str_cmp;
diff --git a/src/pies.c b/src/pies.c
index 98488a6..6105ae6 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -521,43 +521,12 @@ config_array_to_argv (grecs_value_t *val, grecs_locus_t *locus, size_t *pargc)
if (pargc)
*pargc = argc;
return argv;
}
static int
-_cb_command (enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
-{
- struct component *comp = varptr;
- struct wordsplit ws;
-
- switch (value->type)
- {
- case GRECS_TYPE_STRING:
- if (wordsplit (value->v.string, &ws, WRDSF_DEFFLAGS))
- {
- grecs_error (locus, 0, "wordsplit: %s", strerror (errno));
- return 1;
- }
- wordsplit_get_words (&ws, &comp->argc, &comp->argv);
- wordsplit_free (&ws);
- break;
-
- case GRECS_TYPE_ARRAY:
- comp->argv = config_array_to_argv (value, locus, &comp->argc);
- break;
-
- case GRECS_TYPE_LIST:
- grecs_error (locus, 0, _("unexpected list"));
- return 1;
- }
- return 0;
-}
-
-static int
_cb_umask (enum grecs_callback_command cmd,
grecs_locus_t *locus,
void *varptr, grecs_value_t *value, void *cb_data)
{
mode_t *pmode = varptr;
char *p;
@@ -586,19 +555,15 @@ _cb_env (enum grecs_callback_command cmd,
char ***penv = varptr;
struct wordsplit ws;
switch (value->type)
{
case GRECS_TYPE_STRING:
- if (wordsplit (value->v.string, &ws, WRDSF_DEFFLAGS))
- {
- grecs_error (locus, 0, "wordsplit: %s", strerror (errno));
- return 1;
- }
- wordsplit_get_words (&ws, &argc, &argv);
- wordsplit_free (&ws);
+ argv = grecs_calloc (2, sizeof (argv[0]));
+ argv[0] = grecs_strdup (value->v.string);
+ argv[1] = NULL;
break;
case GRECS_TYPE_ARRAY:
argv = config_array_to_argv (value, locus, NULL);
break;
@@ -884,12 +849,13 @@ str_to_cf (const char *string, int *flags)
{ "tcpmuxplus", CF_TCPMUXPLUS },
{ "internal", CF_INTERNAL },
{ "sockenv", CF_SOCKENV },
{ "resolve", CF_RESOLVE },
{ "siggroup", CF_SIGGROUP },
{ "nullinput", CF_NULLINPUT },
+ { "shell", CF_SHELL },
{ NULL }
};
if (len > 2 && memcmp (string, "no", 2) == 0)
{
neg++;
@@ -1011,15 +977,15 @@ struct grecs_keyword component_keywords[] = {
NULL,
},
{"command",
NULL,
N_("Command line."),
grecs_type_string, GRECS_DFLT,
- NULL, 0,
- _cb_command,
- },
+ NULL, offsetof (struct component, command),
+ NULL,
+ },
{"prerequisites",
N_("list"),
N_("List of prerequisites."),
grecs_type_string, GRECS_LIST, NULL, offsetof (struct component, prereq),
NULL,
},
diff --git a/src/pies.h b/src/pies.h
index 74cb346..2e544e1 100644
--- a/src/pies.h
+++ b/src/pies.h
@@ -203,16 +203,16 @@ enum pies_comp_mode
it */
#define CF_INTERNAL 0x020 /* An internal inetd service */
#define CF_SOCKENV 0x040 /* Component wants socket information in
the environment */
#define CF_RESOLVE 0x080 /* Resolve IP addresses */
#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_REMOVE 0x400 /* Marked for removal */
+#define CF_REMOVE 0xf000 /* Marked for removal */
#define ISCF_TCPMUX(f) ((f) & (CF_TCPMUX | CF_TCPMUXPLUS))
struct prog;
struct component
@@ -223,12 +223,13 @@ struct component
size_t ref_count; /* Reference count. */
struct prog *prog; /* Prog associated with this component. */
enum pies_comp_mode mode;
char *tag; /* Entry tag (for diagnostics purposes) */
char *program; /* Program name */
+ char *command; /* Full command line */
size_t argc; /* Number of command line arguments */
char **argv; /* Program command line */
char **env; /* Program environment */
char *dir; /* Working directory */
struct grecs_list *prereq; /* Prerequisites */
struct grecs_list *depend; /* Dependency targets */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b404ed4..39899c8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -49,12 +49,13 @@ TESTSUITE_AT = \
control.at\
cyclic.at\
respawn.at\
redirect.at\
ret-exec.at\
ret-notify.at\
+ shell.at\
startup.at\
shutdown.at\
version.at
TESTSUITE = $(srcdir)/testsuite
M4=m4
diff --git a/tests/aux/respawn b/tests/aux/respawn
index 11d59f6..cd9687a 100755
--- a/tests/aux/respawn
+++ b/tests/aux/respawn
@@ -2,13 +2,13 @@
# usage: respawn [-append] [-stderr FILE] [-stdout FILE] [-sleep TIME]
# [-pid FILE] [-tag STRING] [-exit CODE]
append=0
unset name
-time=10
+time=1
tag=$0
code=0
while [ $# -ne 0 ]
do
arg=$1
diff --git a/tests/respawn.at b/tests/respawn.at
index 4a8e3a7..6b51ca6 100644
--- a/tests/respawn.at
+++ b/tests/respawn.at
@@ -31,13 +31,13 @@ pies --config-file control.conf --config-file pies.conf
n=0
while :
do
if test -f $comp_pid_file; then
lines=`wc -l $comp_pid_file | awk '{print $1}'`
- if test "$lines" -ge 3 ; then
+ if test "$lines" -ge 2 ; then
break
fi
fi
sleep 1
n=$(($n + 1))
if test $n -gt 35; then
diff --git a/tests/shell.at b/tests/shell.at
new file mode 100644
index 0000000..0ef2271
--- /dev/null
+++ b/tests/shell.at
@@ -0,0 +1,58 @@
+# This file is part of GNU pies testsuite. -*- Autotest -*-
+# Copyright (C) 2016-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/>.
+
+AT_SETUP([flags shell])
+
+AT_CHECK([
+PIES_XFAIL_CHECK
+PIES_CONTROL_INIT
+outfile=$PWD/respawn.out
+cat > pies.conf <<_EOT
+component test {
+ mode respawn;
+ flags shell;
+ command "$auxdir/respawn -tag respawn > $outfile";
+}
+_EOT
+
+pies --config-file control.conf --config-file pies.conf
+
+n=0
+while :
+do
+ if test -f $outfile; then
+ lines=`wc -l $outfile | awk '{print $1}'`
+ if test "$lines" -ge 2 ; then
+ break
+ fi
+ fi
+ sleep 1
+ n=$(($n + 1))
+ if test $n -gt 35; then
+ echo >&2 "timed out"
+ break
+ fi
+done
+
+PIES_STOP
+head -n3 $outfile
+],
+[0],
+[respawn: start
+respawn: stop
+])
+
+AT_CLEANUP
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 6775ee7..28d1f9d 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -64,6 +64,7 @@ AT_BANNER([Components])
m4_include([respawn.at])
m4_include([redirect.at])
m4_include([ret-exec.at])
m4_include([ret-notify.at])
m4_include([startup.at])
m4_include([shutdown.at])
+m4_include([shell.at])

Return to:

Send suggestions and report system problems to the System administrator.