2000-03-21 J.T. Conklin <jtc@redback.com>
[platform/upstream/binutils.git] / gdb / environ.c
1 /* environ.c -- library for manipulating environments for GNU.
2    Copyright (C) 1986, 1989 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 59 Temple Place - Suite 330,
17    Boston, MA 02111-1307, USA.  */
18
19 #define min(a, b) ((a) < (b) ? (a) : (b))
20 #define max(a, b) ((a) > (b) ? (a) : (b))
21
22 #include "defs.h"
23 #include "environ.h"
24 #include "gdb_string.h"
25 #include "gdbcore.h"
26 \f
27
28 /* Return a new environment object.  */
29
30 struct environ *
31 make_environ ()
32 {
33   register struct environ *e;
34
35   e = (struct environ *) xmalloc (sizeof (struct environ));
36
37   e->allocated = 10;
38   e->vector = (char **) xmalloc ((e->allocated + 1) * sizeof (char *));
39   e->vector[0] = 0;
40   return e;
41 }
42
43 /* Free an environment and all the strings in it.  */
44
45 void
46 free_environ (e)
47      register struct environ *e;
48 {
49   register char **vector = e->vector;
50
51   while (*vector)
52     free (*vector++);
53
54   free (e);
55 }
56
57 /* Copy the environment given to this process into E.
58    Also copies all the strings in it, so we can be sure
59    that all strings in these environments are safe to free.  */
60
61 void
62 init_environ (e)
63      register struct environ *e;
64 {
65   extern char **environ;
66   register int i;
67
68   if (environ == NULL)
69     return;
70
71   for (i = 0; environ[i]; i++) /*EMPTY */ ;
72
73   if (e->allocated < i)
74     {
75       e->allocated = max (i, e->allocated + 10);
76       e->vector = (char **) xrealloc ((char *) e->vector,
77                                       (e->allocated + 1) * sizeof (char *));
78     }
79
80   memcpy (e->vector, environ, (i + 1) * sizeof (char *));
81
82   while (--i >= 0)
83     {
84       register int len = strlen (e->vector[i]);
85       register char *new = (char *) xmalloc (len + 1);
86       memcpy (new, e->vector[i], len + 1);
87       e->vector[i] = new;
88     }
89 }
90
91 /* Return the vector of environment E.
92    This is used to get something to pass to execve.  */
93
94 char **
95 environ_vector (e)
96      struct environ *e;
97 {
98   return e->vector;
99 }
100 \f
101 /* Return the value in environment E of variable VAR.  */
102
103 char *
104 get_in_environ (e, var)
105      const struct environ *e;
106      const char *var;
107 {
108   register int len = strlen (var);
109   register char **vector = e->vector;
110   register char *s;
111
112   for (; (s = *vector) != NULL; vector++)
113     if (STREQN (s, var, len) && s[len] == '=')
114       return &s[len + 1];
115
116   return 0;
117 }
118
119 /* Store the value in E of VAR as VALUE.  */
120
121 void
122 set_in_environ (e, var, value)
123      struct environ *e;
124      const char *var;
125      const char *value;
126 {
127   register int i;
128   register int len = strlen (var);
129   register char **vector = e->vector;
130   register char *s;
131
132   for (i = 0; (s = vector[i]) != NULL; i++)
133     if (STREQN (s, var, len) && s[len] == '=')
134       break;
135
136   if (s == 0)
137     {
138       if (i == e->allocated)
139         {
140           e->allocated += 10;
141           vector = (char **) xrealloc ((char *) vector,
142                                        (e->allocated + 1) * sizeof (char *));
143           e->vector = vector;
144         }
145       vector[i + 1] = 0;
146     }
147   else
148     free (s);
149
150   s = (char *) xmalloc (len + strlen (value) + 2);
151   strcpy (s, var);
152   strcat (s, "=");
153   strcat (s, value);
154   vector[i] = s;
155
156   /* This used to handle setting the PATH and GNUTARGET variables
157      specially.  The latter has been replaced by "set gnutarget"
158      (which has worked since GDB 4.11).  The former affects searching
159      the PATH to find SHELL, and searching the PATH to find the
160      argument of "symbol-file" or "exec-file".  Maybe we should have
161      some kind of "set exec-path" for that.  But in any event, having
162      "set env" affect anything besides the inferior is a bad idea.
163      What if we want to change the environment we pass to the program
164      without afecting GDB's behavior?  */
165
166   return;
167 }
168
169 /* Remove the setting for variable VAR from environment E.  */
170
171 void
172 unset_in_environ (e, var)
173      struct environ *e;
174      char *var;
175 {
176   register int len = strlen (var);
177   register char **vector = e->vector;
178   register char *s;
179
180   for (; (s = *vector) != NULL; vector++)
181     {
182       if (STREQN (s, var, len) && s[len] == '=')
183         {
184           free (s);
185           /* Walk through the vector, shuffling args down by one, including
186              the NULL terminator.  Can't use memcpy() here since the regions
187              overlap, and memmove() might not be available. */
188           while ((vector[0] = vector[1]) != NULL)
189             {
190               vector++;
191             }
192           break;
193         }
194     }
195 }