aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS8
-rw-r--r--doc/pies.texi15
-rw-r--r--lib/envop.c51
-rw-r--r--src/pies.c22
4 files changed, 77 insertions, 19 deletions
diff --git a/NEWS b/NEWS
index 4ee1ae5..f5be6dd 100644
--- a/NEWS
+++ b/NEWS
@@ -1,13 +1,13 @@
-GNU Pies NEWS -- history of user-visible changes. 2019-06-06
+GNU Pies NEWS -- history of user-visible changes. 2019-06-07
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.91 (git)
* New option --no-init
The --no-init option instructs pies not to switch to init mode if its
PID is 1. Use this option if you run pies as a process manager in a
docker container.
@@ -46,24 +46,30 @@ It can contain the following sub-statements:
** clear
Clears the environment
** keep NAME
Keeps the variable NAME when clearing the environment. Implies
"clear". NAME can be a globbing pattern, in which case all
variables matching the pattern are retained.
** set "NAME=VALUE"
Sets the environment variable for the component. VALUE is subject
to variable expansion.
+** eval "VALUE"
+Perform variable expansion on VALUE and discard the result (similar
+to the shell ":" command). Useful for side effects, e.g.:
+
+ eval ${HOME:=/home/t}
+
** unset NAME
Unsets the variable. NAME can be a globbing pattern, in which case all
variables matching the pattern are unset.
Example:
env {
clear;
keep PATH;
keep MANPATH;
keep "LC_*";
set "MANPATH=$MANPATH${MANPATH:+:}/usr/local/man";
diff --git a/doc/pies.texi b/doc/pies.texi
index 63064e5..4bd2f8f 100644
--- a/doc/pies.texi
+++ b/doc/pies.texi
@@ -1055,24 +1055,25 @@ up to 1.3 and is still retained for backward compatibility. It is
described in @ref{env legacy syntax}. This subsection describes the
modern compount syntax.
@deffn {Config: component} env @{ ... @}
The compound @code{env} statement has the following syntax:
@example
@group
env @{
clear;
keep @var{pattern};
set "@var{name}=@var{value}";
+ eval "@var{value}";
unset @var{pattern};
@}
@end group
@end example
@end deffn
Statements inside the @code{env} block define operations that
modify the environment. The @code{clear} and @code{keep} statements
are executed first. Then, the @code{set} and @code{unset} statements
are applied in the order of their appearance in the configuration.
@deffn {env} clear
@@ -1114,24 +1115,38 @@ The @code{set} and @code{unset} (see below) statements are executed in
order of their appearance. For example
@example
@group
env @{
set "MYLIB=$HOME/lib";
set "LD_LIBRARY_PATH=$LD_LIBRARY_PATH$@{LD_LIBRARY_PATH:+:@}$MYLIB";
@}
@end group
@end example
@end deffn
+@deffn {env} eval "@var{value}"
+Perform variable expansion on @var{value} and discard the result. This
+is useful for side-effects. For example, to provide default value for
+the @env{LD_LIBRARY_PATH} variable, one may write:
+
+@example
+@group
+env @{
+ eval "$@{LD_LIBRARY_PATH:=/usr/local/lib@}";
+@}
+@end group
+@end example
+@end deffn
+
@deffn {env} unset @var{pattern}
Unset environment variables matching @var{pattern}. The following
will unset the @env{LOGIN} variable:
@example
unset LOGIN;
@end example
@noindent
The following will unset all variables starting with @samp{LD_}:
@example
diff --git a/lib/envop.c b/lib/envop.c
index ce24b92..93bd425 100644
--- a/lib/envop.c
+++ b/lib/envop.c
@@ -158,49 +158,62 @@ environ_add (environ_t *env, char const *def)
return -1;
}
return 0;
}
int
environ_set (environ_t *env, char const *name, char const *value)
{
size_t len;
char *def;
struct wordsplit ws;
- if (!name)
+ if (!value)
{
- errno = EINVAL;
- return -1;
+ if (!name)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+ return environ_unset (env, name, value);
}
- if (!value)
- return environ_unset (env, name, value);
ws.ws_env = (char const **) env->env_base;
if (wordsplit (value, &ws,
WRDSF_NOSPLIT
| WRDSF_QUOTE
| WRDSF_NOCMD /* FIXME */
| WRDSF_SQUEEZE_DELIMS
| WRDSF_CESCAPES
| WRDSF_ENV
| WRDSF_PATHEXPAND))
{
int ec = errno;
wordsplit_free (&ws);
errno = ec;
return -1;
}
- if (strcmp (name, ":") == 0)
+ if (ws.ws_envbuf)
+ {
+ free (env->env_base);
+ env->env_base = ws.ws_envbuf;
+ env->env_count = ws.ws_envidx;
+ env->env_max = ws.ws_envsiz;
+ ws.ws_envbuf = NULL;
+ ws.ws_envidx = 0;
+ ws.ws_envsiz = 0;
+ }
+
+ if (name == NULL || strcmp (name, ":") == 0)
{
wordsplit_free (&ws);
return 0;
}
len = strlen (name) + strlen (ws.ws_wordv[0]) + 2;
def = malloc (len);
if (!def)
{
int ec = errno;
wordsplit_free (&ws);
errno = ec;
@@ -325,70 +338,72 @@ valid_envar_name (char const *name)
if (!(isalnum (*name) || *name == '_'))
return 0;
}
return 1;
}
int
envop_entry_add (struct envop_entry **head,
enum envop_code code, char const *name, char const *value)
{
struct envop_entry *op;
size_t s;
+ char *p;
switch (code)
{
case envop_clear:
break;
case envop_set:
- if (!name || !(*name == ':' || valid_envar_name (name)))
+ if (name && !(*name == ':' || valid_envar_name (name)))
{
errno = EINVAL;
return -1;
}
break;
case envop_keep:
case envop_unset:
break;
default:
errno = EINVAL;
return -1;
}
s = sizeof (op[0]);
if (name)
- {
- s += strlen (name) + 1;
- if (value)
- s += strlen (value) + 1;
- }
+ s += strlen (name) + 1;
+ if (value)
+ s += strlen (value) + 1;
op = malloc (s);
if (!op)
return -1;
op->next = NULL;
op->code = code;
op->name = NULL;
op->value = NULL;
+
+ p = (char*)(op + 1);
if (name)
{
- op->name = (char*)(op + 1);
+ op->name = p;
strcpy (op->name, name);
- if (value)
- {
- op->value = op->name + strlen (name) + 1;
- strcpy (op->value, value);
- }
+ p += strlen (name) + 1;
+ }
+ if (value)
+ {
+ op->value = p;
+ strcpy (op->value, value);
}
envop_entry_insert (head, op);
return 0;
}
static int
envopmatch (struct envop_entry *op, char const *var, int len)
{
if (op->value)
{
if (strncmp (op->name, var, len) == 0)
return strcmp (var + len + 1, op->value);
diff --git a/src/pies.c b/src/pies.c
index 1f5fb8f..73d33a0 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -777,24 +777,40 @@ _cb_env_set (enum grecs_callback_command cmd,
if (grecs_assert_node_value_type (cmd, node, GRECS_TYPE_STRING))
return 1;
p = strchr (value->v.string, '=');
if (p)
*p++ = 0;
if (envop_entry_add (&comp->envop, envop_set, value->v.string, p))
grecs_error (locus, errno, "envop_entry_add");
return 0;
}
static int
+_cb_env_eval (enum grecs_callback_command cmd,
+ grecs_node_t *node,
+ void *varptr, void *cb_data)
+{
+ grecs_locus_t *locus = &node->locus;
+ grecs_value_t *value = node->v.value;
+ struct component *comp = varptr;
+
+ if (grecs_assert_node_value_type (cmd, node, GRECS_TYPE_STRING))
+ return 1;
+ if (envop_entry_add (&comp->envop, envop_set, NULL, value->v.string))
+ grecs_error (locus, errno, "envop_entry_add");
+ return 0;
+}
+
+static int
_cb_env_unset (enum grecs_callback_command cmd,
grecs_node_t *node,
void *varptr, void *cb_data)
{
grecs_locus_t *locus = &node->locus;
grecs_value_t *value = node->v.value;
struct component *comp = varptr;
char *p;
if (grecs_assert_node_value_type (cmd, node, GRECS_TYPE_STRING))
return 1;
p = strchr (value->v.string, '=');
@@ -816,24 +832,30 @@ struct grecs_keyword cb_env_keywords[] = {
N_("name[=value]"),
N_("Keep this variable. Unless value is supplied, name can contain wildcards.\n"
"Implies \"clear yes\"."),
grecs_type_string, GRECS_DFLT,
NULL, 0,
_cb_env_keep },
{ "set",
N_("name=value"),
N_("Set environment variable. Note, that argument must be quoted."),
grecs_type_string, GRECS_DFLT,
NULL, 0,
_cb_env_set },
+ { "eval",
+ N_("string"),
+ N_("Evaluate string. Useful for side-effects, e.g. eval ${X:=2}."),
+ grecs_type_string, GRECS_DFLT,
+ NULL, 0,
+ _cb_env_eval },
{ "unset",
N_("name"),
N_("Unset environment variable. Name can contain wildcards."),
grecs_type_string, GRECS_DFLT,
NULL, 0,
_cb_env_unset },
{ NULL }
};
int
string_to_syslog_priority (const char *key, int *pres)

Return to:

Send suggestions and report system problems to the System administrator.