diff options
Diffstat (limited to 'src/pies.c')
-rw-r--r-- | src/pies.c | 278 |
1 files changed, 266 insertions, 12 deletions
@@ -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"), |