diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2016-08-20 09:23:48 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2016-08-20 09:23:48 +0300 |
commit | cee62ab20bf767c3a07562ad30c67126ea3bab32 (patch) | |
tree | f432c01460d9d820cf92de7a55b17109715cf12d | |
parent | 6dd16ac66166ef62fcfc499c184a1b86ca82b227 (diff) | |
download | pies-cee62ab20bf767c3a07562ad30c67126ea3bab32.tar.gz pies-cee62ab20bf767c3a07562ad30c67126ea3bab32.tar.bz2 |
Fix environment modification code
Port fixes from GNU rush
-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 | |||
@@ -659,22 +659,44 @@ add_env (const char *name, const char *value) | |||
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 | { |
@@ -710,3 +732,3 @@ env_concat (const char *name, size_t namelen, const char *a, const char *b) | |||
710 | strcpy (res + namelen + 1, a); | 732 | strcpy (res + namelen + 1, a); |
711 | strcat (res, b); | 733 | strcat (res + namelen + 1, b); |
712 | } | 734 | } |
@@ -739,3 +761,3 @@ environ_setup (char **hint) | |||
739 | char **new_env; | 761 | char **new_env; |
740 | size_t count, i, n; | 762 | size_t count, i, j, n; |
741 | 763 | ||
@@ -768,3 +790,3 @@ environ_setup (char **hint) | |||
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]; |
@@ -781,2 +803,8 @@ environ_setup (char **hint) | |||
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], '='))) |
@@ -786,16 +814,20 @@ environ_setup (char **hint) | |||
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 | } |