aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2019-06-02 07:40:11 +0300
committerSergey Poznyakoff <gray@gnu.org>2019-06-02 08:03:16 +0300
commitcc298a11a131b162f291d6ee27ba1d7598a1b6c4 (patch)
tree4d82a9a5da05fbfdce0c9bf03e605ecf00baa07a /src
parent1f28935841a69aa8be7eb2e88f580df9c95206d2 (diff)
downloadpies-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.c16
-rw-r--r--src/pies.c278
-rw-r--r--src/pies.h5
-rw-r--r--src/prog.h1
-rw-r--r--src/progman.c310
5 files changed, 323 insertions, 287 deletions
diff --git a/src/comp.c b/src/comp.c
index 499dfe5..d030979 100644
--- a/src/comp.c
+++ b/src/comp.c
@@ -166,24 +166,12 @@ component_create (const char *name)
166void 166void
167component_free (struct component *comp) 167component_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);
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,
544 *pmode = n; 544 *pmode = n;
545 return 0; 545 return 0;
546} 546}
547
548void
549argv_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
548static int 560static int
549_cb_env (enum grecs_callback_command cmd, 561parse_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
663static 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
696static int
697cb_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
721static 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
742static int
743