diff options
-rw-r--r-- | src/progman.c | 82 |
1 files changed, 57 insertions, 25 deletions
diff --git a/src/progman.c b/src/progman.c index fdb829a..43aff48 100644 --- a/src/progman.c +++ b/src/progman.c | |||
@@ -657,26 +657,48 @@ add_env (const char *name, const char *value) | |||
657 | environ[i] = p; | 657 | environ[i] = p; |
658 | } | 658 | } |
659 | 659 | ||
660 | static char * | 660 | /* Find variable NAME in environment ENV. |
661 | find_env (const char *name, int val) | 661 | On success, store the index of the ENV slot in *IDX, |
662 | the offset of the value (position right past '=') in *VALOFF, and | ||
663 | return 0 (IDX and/or VALOFF can be NULL, if that info is not needed). | ||
664 | Return -1 if NAME was not found. */ | ||
665 | static int | ||
666 | find_env_pos (char **env, char *name, size_t *idx, size_t *valoff) | ||
662 | { | 667 | { |
663 | if (environ) | 668 | size_t nlen = strcspn (name, "+="); |
664 | { | 669 | size_t i; |
665 | int nlen = strcspn (name, "+="); | ||
666 | int i; | ||
667 | 670 | ||
668 | for (i = 0; environ[i]; i++) | 671 | for (i = 0; env[i]; i++) |
672 | { | ||
673 | size_t elen = strcspn (env[i], "="); | ||
674 | if (elen == nlen && memcmp (name, env[i], nlen) == 0) | ||
669 | { | 675 | { |
670 | size_t elen = strcspn (environ[i], "="); | 676 | if (idx) |
671 | if (elen == nlen && memcmp (name, environ[i], nlen) == 0) | 677 | *idx = i; |
672 | return val ? environ[i] + elen + 1 : environ[i]; | 678 | if (valoff) |
679 | *valoff = elen + 1; | ||
680 | return 0; | ||
673 | } | 681 | } |
674 | } | 682 | } |
675 | return NULL; | 683 | return -1; |
684 | } | ||
685 | |||
686 | /* Find variable NAME in environment ENV. | ||
687 | On success, return pointer to the variable assignment (if VAL is 0), | ||
688 | or to the value (if VAL is 1). | ||
689 | Return NULL if NAME is not present in ENV. */ | ||
690 | static char * | ||
691 | find_env_ptr (char **env, char *name, int val) | ||
692 | { | ||
693 | size_t i, j; | ||
694 | if (find_env_pos (env, name, &i, &j)) | ||
695 | return NULL; | ||
696 | return val ? env[i] + j : env[i]; | ||
676 | } | 697 | } |
677 | 698 | ||
699 | /* Return 1 if ENV contains a matching unset statement for variable NAME. */ | ||
678 | static int | 700 | static int |
679 | locate_unset (char **env, const char *name) | 701 | var_is_unset (char **env, const char *name) |
680 | { | 702 | { |
681 | int i; | 703 | int i; |
682 | int nlen = strcspn (name, "="); | 704 | int nlen = strcspn (name, "="); |
@@ -708,7 +730,7 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b) | |||
708 | { | 730 | { |
709 | res = grecs_malloc (namelen + 1 + strlen (a) + strlen (b) + 1); | 731 | res = grecs_malloc (namelen + 1 + strlen (a) + strlen (b) + 1); |
710 | strcpy (res + namelen + 1, a); | 732 | strcpy (res + namelen + 1, a); |
711 | strcat (res, b); | 733 | strcat (res + namelen + 1, b); |
712 | } | 734 | } |
713 | else if (a) | 735 | else if (a) |
714 | { | 736 | { |
@@ -737,7 +759,7 @@ environ_setup (char **hint) | |||
737 | { | 759 | { |
738 | char **old_env = environ; | 760 | char **old_env = environ; |
739 | char **new_env; | 761 | char **new_env; |
740 | size_t count, i, n; | 762 | size_t count, i, j, n; |
741 | 763 | ||
742 | if (!hint) | 764 | if (!hint) |
743 | return; | 765 | return; |
@@ -766,7 +788,7 @@ environ_setup (char **hint) | |||
766 | if (old_env) | 788 | if (old_env) |
767 | for (i = 0; old_env[i]; i++) | 789 | for (i = 0; old_env[i]; i++) |
768 | { | 790 | { |
769 | if (!locate_unset (hint, old_env[i])) | 791 | if (!var_is_unset (hint, old_env[i])) |
770 | new_env[n++] = old_env[i]; | 792 | new_env[n++] = old_env[i]; |
771 | } | 793 | } |
772 | 794 | ||
@@ -779,25 +801,35 @@ environ_setup (char **hint) | |||
779 | /* Skip unset directives. */ | 801 | /* Skip unset directives. */ |
780 | continue; | 802 | continue; |
781 | } | 803 | } |
804 | |||
805 | /* Find the slot for the variable. Use next available | ||
806 | slot if there's no such variable in new_env */ | ||
807 | if (find_env_pos (new_env, hint[i], &j, NULL)) | ||
808 | j = n; | ||
809 | |||
782 | if ((p = strchr (hint[i], '='))) | 810 | if ((p = strchr (hint[i], '='))) |
783 | { | 811 | { |
784 | if (p == hint[i]) | 812 | if (p == hint[i]) |
785 | continue; /* Ignore erroneous entry */ | 813 | continue; /* Ignore erroneous entry */ |
786 | if (p[-1] == '+') | 814 | if (p[-1] == '+') |
787 | new_env[n++] = env_concat (hint[i], p - hint[i] - 1, | 815 | new_env[j] = env_concat (hint[i], p - hint[i] - 1, |
788 | find_env(hint[i], 1), p + 1); | 816 | find_env_ptr (environ, hint[i], 1), |
817 | p + 1); | ||
789 | else if (p[1] == '+') | 818 | else if (p[1] == '+') |
790 | new_env[n++] = env_concat (hint[i], p - hint[i], | 819 | new_env[j] = env_concat (hint[i], p - hint[i], |
791 | p + 2, find_env(hint[i], 1)); | 820 | p + 2, |
821 | find_env_ptr (environ, hint[i], 1)); | ||
792 | else | 822 | else |
793 | new_env[n++] = hint[i]; | 823 | new_env[j] = hint[i]; |
794 | } | 824 | } |
825 | else if ((p = find_env_ptr (environ, hint[i], 0))) | ||
826 | new_env[j] = p; | ||
795 | else | 827 | else |
796 | { | 828 | continue; |
797 | p = find_env (hint[i], 0); | 829 | |
798 | if (p) | 830 | /* Adjust environment size */ |
799 | new_env[n++] = p; | 831 | if (j == n) |
800 | } | 832 | ++n; |
801 | } | 833 | } |
802 | new_env[n] = NULL; | 834 | new_env[n] = NULL; |
803 | 835 | ||