diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-06-02 07:40:11 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-06-02 08:03:16 +0300 |
commit | cc298a11a131b162f291d6ee27ba1d7598a1b6c4 (patch) | |
tree | 4d82a9a5da05fbfdce0c9bf03e605ecf00baa07a /src | |
parent | 1f28935841a69aa8be7eb2e88f580df9c95206d2 (diff) | |
download | pies-cc298a11a131b162f291d6ee27ba1d7598a1b6c4.tar.gz pies-cc298a11a131b162f291d6ee27ba1d7598a1b6c4.tar.bz2 |
New configuration statement for manipulating the environment.
The "env" statement is now a compound statement. It can contain four
substatements: "clear" to clear the environment, "keep" to retain
certain variable while clearing it, "set" to set a variable, and
"unset" to unset a variable or variables.
Both "keep" and "unset" can take globbing pattern as their argument,
in which case they affect all variable matching that pattern.
The value part in the "set" statement is subject to variable expansion,
e.g.
set "MANPATH=$MANPATH${MANPATH:+:}/usr/local/man"
The support for the old one-line syntax of "env" is retained for
backward compatibility.
This commit also fixes redirection to a file: new data are appended
to the file, instead of overwriting it.
* lib/Makefile.am: Add new files.
* lib/envop.c: New file.
* lib/envop.h: New file.
* lib/wildmatch.c: New file.
* src/comp.c (component_free): Update.
* src/pies.c (argv_free): New function.
(parse_legacy_env): New function.
(_cb_env): Remove.
(cb_env_section_parser): New function.
(cb_env_keywords): New keywords for the "env" block statement:
clear, keep, set, unset.
(component_keywords): New compount statement: env.
Old usage retained for backward compatibility.
* src/pies.h: Include "envop.h"
(component)<env>: Remove.
<envop>: New field.
* src/prog.h (prog)<env>: New field.
* src/progman.c (redirect_to_file): Position to the end of file.
(DEBUG_ENVIRON): Remove macro.
(debug_environ): New function.
(environ_setup): Remove.
(prog_sockenv): Use environ_set to modify local copy of environment.
(prog_start_prologue): Use environ_create + envop_exec to create and
modify the environment.
(prog_execute): Set environment to prog-local copy.
* tests/.gitignore: Build envtest
* tests/Makefile.am: Add new tests.
* tests/testsuite.at: Add environment tests.
* tests/envop.at: New file.
* tests/envtest.c: New file.
* tests/env.at: New file.
* tests/redirect.at: Check first two lines of the output file.
Diffstat (limited to 'src')
-rw-r--r-- | src/comp.c | 16 | ||||
-rw-r--r-- | src/pies.c | 278 | ||||
-rw-r--r-- | src/pies.h | 5 | ||||
-rw-r--r-- | src/prog.h | 1 | ||||
-rw-r--r-- | src/progman.c | 310 |
5 files changed, 323 insertions, 287 deletions
@@ -166,24 +166,12 @@ component_create (const char *name) | |||
166 | void | 166 | void |
167 | component_free (struct component *comp) | 167 | component_free (struct component *comp) |
168 | { | 168 | { |
169 | size_t i; | ||
170 | |||
171 | component_unlink (comp); | 169 | component_unlink (comp); |
172 | free (comp->tag); | 170 | free (comp->tag); |
173 | free (comp->program); | 171 | free (comp->program); |
174 | free (comp->command); | 172 | free (comp->command); |
175 | if (comp->argv) | 173 | argv_free (comp->argv); |
176 | { | 174 | envop_free (comp->envop); |
177 | for (i = 0; i < comp->argc; i++) | ||
178 | free (comp->argv[i]); | ||
179 | free (comp->argv); | ||
180 | } | ||
181 | if (comp->env) | ||
182 | { | ||
183 | for (i = 0; comp->env[i]; i++) | ||
184 | free (comp->env[i]); | ||
185 | free (comp->env); | ||
186 | } | ||
187 | free (comp->dir); | 175 | free (comp->dir); |
188 | grecs_list_free (comp->prereq); | 176 | grecs_list_free (comp->prereq); |
189 | grecs_list_free (comp->depend); | 177 | grecs_list_free (comp->depend); |
@@ -544,16 +544,127 @@ _cb_umask (enum grecs_callback_command cmd, | |||
544 | *pmode = n; | 544 | *pmode = n; |
545 | return 0; | 545 | return 0; |
546 | } | 546 | } |
547 | |||
548 | void | ||
549 | argv_free (char **argv) | ||
550 | { | ||
551 | if (argv) | ||
552 | { | ||
553 | size_t i; | ||
554 | for (i = 0; argv[i]; i++) | ||
555 | free (argv[i]); | ||
556 | free (argv); | ||
557 | } | ||
558 | } | ||
547 | 559 | ||
548 | static int | 560 | static int |
549 | _cb_env (enum grecs_callback_command cmd, | 561 | parse_legacy_env (char **argv, envop_t **envop) |
550 | grecs_locus_t *locus, | 562 | { |
551 | void *varptr, grecs_value_t *value, void *cb_data) | 563 | size_t i = 0; |
564 | int rc; | ||
565 | char *name; | ||
566 | |||
567 | if (strcmp (argv[0], "-") == 0) | ||
568 | { | ||
569 | rc = envop_entry_add (envop, envop_clear, NULL, NULL); | ||
570 | if (rc) | ||
571 | return rc; | ||
572 | i++; | ||
573 | } | ||
574 | for (; (name = argv[i]) != NULL; i++) | ||
575 | { | ||
576 | char *name = argv[i]; | ||
577 | size_t len = strcspn (name, "="); | ||
578 | char *value; | ||
579 | char *mem = NULL; | ||
580 | size_t msize = 0; | ||
581 | enum envop_code code; | ||
582 | |||
583 | if (name[0] == '-') | ||
584 | { | ||
585 | /* Unset directive */ | ||
586 | name++; | ||
587 | len--; | ||
588 | |||
589 | if (name[len]) | ||
590 | { | ||
591 | name[len] = 0; | ||
592 | value = name + len + 1; | ||
593 | } | ||
594 | else | ||
595 | value = NULL; | ||
596 | |||
597 | code = envop_unset; | ||
598 | } | ||
599 | else if (name[len]) | ||
600 | { | ||
601 | size_t vlen; | ||
602 | |||
603 | if (len == 0) | ||
604 | /* Skip erroneous entry */ | ||
605 | continue; | ||
606 | value = name + len + 1; | ||
607 | vlen = strlen (value); | ||
608 | name[len] = 0; | ||
609 | if (name[len-1] == '+') | ||
610 | { | ||
611 | name[--len] = 0; | ||
612 | if (c_ispunct (value[0])) | ||
613 | { | ||
614 | msize = 2*len + 9 + vlen + 1; | ||
615 | mem = grecs_malloc (msize); | ||
616 | snprintf (mem, msize, "${%s:-}${%s+%c}%s", | ||
617 | name, name, value[0], value + 1); | ||
618 | } | ||
619 | else | ||
620 | { | ||
621 | msize = len + vlen + 6; | ||
622 | snprintf (mem, msize, "${%s:-}%s", name, value); | ||
623 | } | ||
624 | value = mem; | ||
625 | } | ||
626 | else if (value[0] == '+') | ||
627 | { | ||
628 | value++; | ||
629 | vlen--; | ||
630 | |||
631 | if (vlen > 0 && c_ispunct (value[vlen-1])) | ||
632 | { | ||
633 | int c = value[vlen-1]; | ||
634 | value[--vlen] = 0; | ||
635 | |||
636 | msize = 2*len + 10 + vlen + 1; | ||
637 | mem = grecs_malloc (msize); | ||
638 | snprintf (mem, msize, "%s${%s+%c}${%s:-}", | ||
639 | value, name, c, name); | ||
640 | } | ||
641 | else | ||
642 | { | ||
643 | msize = len + vlen + 6; | ||
644 | snprintf (mem, msize, "%s${%s:-}", value, name); | ||
645 | } | ||
646 | value = mem; | ||
647 | } | ||
648 | code = envop_set; | ||
649 | } | ||
650 | else | ||
651 | { | ||
652 | value = NULL; | ||
653 | code = envop_keep; | ||
654 | } | ||
655 | rc = envop_entry_add (envop, code, name, value); | ||
656 | free (mem); | ||
657 | if (rc) | ||
658 | return rc; | ||
659 | } | ||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | static int | ||
664 | _cb_env (envop_t **envop, grecs_value_t *value, grecs_locus_t *locus) | ||
552 | { | 665 | { |
553 | size_t argc; | ||
554 | char **argv; | 666 | char **argv; |
555 | char ***penv = varptr; | 667 | int rc; |
556 | struct wordsplit ws; | ||
557 | 668 | ||
558 | switch (value->type) | 669 | switch (value->type) |
559 | { | 670 | { |
@@ -572,11 +683,147 @@ _cb_env (enum grecs_callback_command cmd, | |||
572 | return 1; | 683 | return 1; |
573 | } | 684 | } |
574 | 685 | ||
575 | *penv = argv; | 686 | rc = parse_legacy_env (argv, envop); |
687 | argv_free (argv); | ||
688 | if (rc) | ||
689 | { | ||
690 | grecs_error (locus, errno, _("can't parse legacy env statement")); | ||
691 | return 1; | ||
692 | } | ||
693 | return 0; | ||
694 | } | ||
695 | |||
696 | static int | ||
697 | cb_env_section_parser (enum grecs_callback_command cmd, | ||
698 | grecs_locus_t *locus, | ||
699 | void *varptr, | ||
700 | grecs_value_t *value, void *cb_data) | ||
701 | { | ||
702 | struct component *comp = varptr; | ||
703 | |||
704 | switch (cmd) | ||
705 | { | ||
706 | case grecs_callback_section_begin: | ||
707 | //FIXME | ||
708 | *(struct component **) cb_data = comp; | ||
709 | break; | ||
710 | |||
711 | case grecs_callback_section_end: | ||
712 | //FIXME | ||
713 | break; | ||
714 | |||
715 | case grecs_callback_set_value: | ||
716 | return _cb_env (&comp->envop, value, locus); | ||
717 | } | ||
718 | return 0; | ||
719 | } | ||
720 | |||
721 | static int | ||
722 | _cb_env_clear (enum grecs_callback_command cmd, | ||
723 | grecs_locus_t *locus, | ||
724 | void *varptr, grecs_value_t *value, void *cb_data) | ||
725 | { | ||
726 | struct component *comp = varptr; | ||
727 | int clear; | ||
728 | |||
729 | if (assert_scalar_stmt (locus, cmd) | ||
730 | || assert_grecs_value_type (locus, value, GRECS_TYPE_STRING)) | ||
731 | return 1; | ||
732 | if (grecs_string_convert(&clear, grecs_type_bool, value->v.string, locus)) | ||
733 | return 1; | ||
734 | if (clear) | ||
735 | { | ||
736 | if (envop_entry_add (&comp->envop, envop_clear, NULL, NULL)) | ||
737 | grecs_error (locus, errno, "envop_entry_add"); | ||
738 | } | ||
576 | return 0; | 739 | return 0; |
577 | } | 740 | } |
578 | |||
579 | 741 | ||
742 | static int | ||
743 |