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