aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/progman.c82
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
660static char * 660/* Find variable NAME in environment ENV.
661find_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. */
665static int
666find_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. */
690static char *
691find_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. */
678static int 700static int
679locate_unset (char **env, const char *name) 701var_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

Return to:

Send suggestions and report system problems to the System administrator.