aboutsummaryrefslogtreecommitdiff
path: root/src/pies.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pies.c')
-rw-r--r--src/pies.c278
1 files changed, 266 insertions, 12 deletions
diff --git a/src/pies.c b/src/pies.c
index 6105ae6..39467a2 100644
--- a/src/pies.c
+++ b/src/pies.c
@@ -544,16 +544,127 @@ _cb_umask (enum grecs_callback_command cmd,
*pmode = n;
return 0;
}
+
+void
+argv_free (char **argv)
+{
+ if (argv)
+ {
+ size_t i;
+ for (i = 0; argv[i]; i++)
+ free (argv[i]);
+ free (argv);
+ }
+}
static int
-_cb_env (enum grecs_callback_command cmd,
- grecs_locus_t *locus,
- void *varptr, grecs_value_t *value, void *cb_data)
+parse_legacy_env (char **argv, envop_t **envop)
+{
+ size_t i = 0;
+ int rc;
+ char *name;
+
+ if (strcmp (argv[0], "-") == 0)
+ {
+ rc = envop_entry_add (envop, envop_clear, NULL, NULL);
+ if (rc)
+ return rc;
+ i++;
+ }
+ for (; (name = argv[i]) != NULL; i++)
+ {
+ char *name = argv[i];
+ size_t len = strcspn (name, "=");
+ char *value;
+ char *mem = NULL;
+ size_t msize = 0;
+ enum envop_code code;
+
+ if (name[0] == '-')
+ {
+ /* Unset directive */
+ name++;
+ len--;
+
+ if (name[len])
+ {
+ name[len] = 0;
+ value = name + len + 1;
+ }
+ else
+ value = NULL;
+
+ code = envop_unset;
+ }
+ else if (name[len])
+ {
+ size_t vlen;
+
+ if (len == 0)
+ /* Skip erroneous entry */
+ continue;
+ value = name + len + 1;
+ vlen = strlen (value);
+ name[len] = 0;
+ if (name[len-1] == '+')
+ {
+ name[--len] = 0;
+ if (c_ispunct (value[0]))
+ {
+ msize = 2*len + 9 + vlen + 1;
+ mem = grecs_malloc (msize);
+ snprintf (mem, msize, "${%s:-}${%s+%c}%s",
+ name, name, value[0], value + 1);
+ }
+ else
+ {
+ msize = len + vlen + 6;
+ snprintf (mem, msize, "${%s:-}%s", name, value);
+ }
+ value = mem;
+ }
+ else if (value[0] == '+')
+ {
+ value++;
+ vlen--;
+
+ if (vlen > 0 && c_ispunct (value[vlen-1]))
+ {
+ int c = value[vlen-1];
+ value[--vlen] = 0;
+
+ msize = 2*len + 10 + vlen + 1;
+ mem = grecs_malloc (msize);
+ snprintf (mem, msize, "%s${%s+%c}${%s:-}",
+ value, name, c, name);
+ }
+ else
+ {
+ msize = len + vlen + 6;
+ snprintf (mem, msize, "%s${%s:-}", value, name);
+ }
+ value = mem;
+ }
+ code = envop_set;
+ }
+ else
+ {
+ value = NULL;
+ code = envop_keep;
+ }
+ rc = envop_entry_add (envop, code, name, value);
+ free (mem);
+ if (rc)
+ return rc;
+ }
+ return 0;
+}
+
+static int
+_cb_env (envop_t **envop, grecs_value_t *value, grecs_locus_t *locus)
{
- size_t argc;
char **argv;
- char ***penv = varptr;
- struct wordsplit ws;
+ int rc;
switch (value->type)
{
@@ -572,11 +683,147 @@ _cb_env (enum grecs_callback_command cmd,
return 1;
}
- *penv = argv;
+ rc = parse_legacy_env (argv, envop);
+ argv_free (argv);
+ if (rc)
+ {
+ grecs_error (locus, errno, _("can't parse legacy env statement"));
+ return 1;
+ }
+ return 0;
+}
+
+static int
+cb_env_section_parser (enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr,
+ grecs_value_t *value, void *cb_data)
+{
+ struct component *comp = varptr;
+
+ switch (cmd)
+ {
+ case grecs_callback_section_begin:
+ //FIXME
+ *(struct component **) cb_data = comp;
+ break;
+
+ case grecs_callback_section_end:
+ //FIXME
+ break;
+
+ case grecs_callback_set_value:
+ return _cb_env (&comp->envop, value, locus);
+ }
+ return 0;
+}
+
+static int
+_cb_env_clear (enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr, grecs_value_t *value, void *cb_data)
+{
+ struct component *comp = varptr;
+ int clear;
+
+ if (assert_scalar_stmt (locus, cmd)
+ || assert_grecs_value_type (locus, value, GRECS_TYPE_STRING))
+ return 1;
+ if (grecs_string_convert(&clear, grecs_type_bool, value->v.string, locus))
+ return 1;
+ if (clear)
+ {
+ if (envop_entry_add (&comp->envop, envop_clear, NULL, NULL))
+ grecs_error (locus, errno, "envop_entry_add");
+ }
return 0;
}
-
+static int
+_cb_env_keep (enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr, grecs_value_t *value, void *cb_data)
+{
+ struct component *comp = varptr;
+ char *p;
+
+ if (assert_scalar_stmt (locus, cmd)
+ || assert_grecs_value_type (locus, value, GRECS_TYPE_STRING))
+ return 1;
+ p = strchr (value->v.string, '=');
+ if (p)
+ *p++ = 0;
+ if (envop_entry_add (&comp->envop, envop_clear, NULL, NULL))
+ grecs_error (locus, errno, "envop_entry_add");
+ if (envop_entry_add (&comp->envop, envop_keep, value->v.string, p))
+ grecs_error (locus, errno, "envop_entry_add");
+ return 0;
+}
+
+static int
+_cb_env_set (enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr, grecs_value_t *value, void *cb_data)
+{
+ struct component *comp = varptr;
+ char *p;
+
+ if (assert_scalar_stmt (locus, cmd)
+ || assert_grecs_value_type (locus, value, 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_unset (enum grecs_callback_command cmd,
+ grecs_locus_t *locus,
+ void *varptr, grecs_value_t *value, void *cb_data)
+{
+ struct component *comp = varptr;
+
+ if (assert_scalar_stmt (locus, cmd)
+ || assert_grecs_value_type (locus, value, GRECS_TYPE_STRING))
+ return 1;
+ if (envop_entry_add (&comp->envop, envop_unset, value->v.string, NULL))
+ grecs_error (locus, errno, "envop_entry_add");
+ return 0;
+}
+
+struct grecs_keyword cb_env_keywords[] = {
+ { "clear",
+ N_("bool"),
+ N_("Clear environment."),
+ grecs_type_bool, GRECS_DFLT,
+ NULL, 0,
+ _cb_env_clear },
+ { "keep",
+ 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 },
+ { "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)
{
@@ -1157,12 +1404,19 @@ struct grecs_keyword component_keywords[] = {
_cb_limits,
},
{"env",
+ NULL,
+ N_("Modify program environment."),
+ grecs_type_section, GRECS_DFLT,
+ NULL, 0,
+ cb_env_section_parser, NULL, cb_env_keywords
+ },
+ {"env",
N_("arg: list"),
- N_("Set program environment. Argument is a list of assignments "
- "separated by white space."),
+ N_("Modify program environment (legacy syntax).\n"
+ "Argument is a list of quoted assignments separated by white space."),
grecs_type_string, GRECS_DFLT,
- NULL, offsetof (struct component, env),
- _cb_env,
+ NULL, 0,
+ cb_env_section_parser, NULL, NULL
},
{"chdir",
N_("dir"),

Return to:

Send suggestions and report system problems to the System administrator.