1/* environ.c -- library for manipulating environments for GNU.
2
3   Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 2000,
4   2003 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 2 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, write to the Free Software
18   Foundation, Inc., 59 Temple Place - Suite 330,
19   Boston, MA 02111-1307, USA.  */
20
21#define min(a, b) ((a) < (b) ? (a) : (b))
22#define max(a, b) ((a) > (b) ? (a) : (b))
23
24#include "defs.h"
25#include "environ.h"
26#include "gdb_string.h"
27
28
29/* Return a new environment object.  */
30
31struct environ *
32make_environ (void)
33{
34  struct environ *e;
35
36  e = (struct environ *) xmalloc (sizeof (struct environ));
37
38  e->allocated = 10;
39  e->vector = (char **) xmalloc ((e->allocated + 1) * sizeof (char *));
40  e->vector[0] = 0;
41  return e;
42}
43
44/* Free an environment and all the strings in it.  */
45
46void
47free_environ (struct environ *e)
48{
49  char **vector = e->vector;
50
51  while (*vector)
52    xfree (*vector++);
53
54  xfree (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
61void
62init_environ (struct environ *e)
63{
64  extern char **environ;
65  int i;
66
67  if (environ == NULL)
68    return;
69
70  for (i = 0; environ[i]; i++) /*EMPTY */ ;
71
72  if (e->allocated < i)
73    {
74      e->allocated = max (i, e->allocated + 10);
75      e->vector = (char **) xrealloc ((char *) e->vector,
76				      (e->allocated + 1) * sizeof (char *));
77    }
78
79  memcpy (e->vector, environ, (i + 1) * sizeof (char *));
80
81  while (--i >= 0)
82    {
83      int len = strlen (e->vector[i]);
84      char *new = (char *) xmalloc (len + 1);
85      memcpy (new, e->vector[i], len + 1);
86      e->vector[i] = new;
87    }
88}
89
90/* Return the vector of environment E.
91   This is used to get something to pass to execve.  */
92
93char **
94environ_vector (struct environ *e)
95{
96  return e->vector;
97}
98
99/* Return the value in environment E of variable VAR.  */
100
101char *
102get_in_environ (const struct environ *e, const char *var)
103{
104  int len = strlen (var);
105  char **vector = e->vector;
106  char *s;
107
108  for (; (s = *vector) != NULL; vector++)
109    if (strncmp (s, var, len) == 0 && s[len] == '=')
110      return &s[len + 1];
111
112  return 0;
113}
114
115/* Store the value in E of VAR as VALUE.  */
116
117void
118set_in_environ (struct environ *e, const char *var, const char *value)
119{
120  int i;
121  int len = strlen (var);
122  char **vector = e->vector;
123  char *s;
124
125  for (i = 0; (s = vector[i]) != NULL; i++)
126    if (strncmp (s, var, len) == 0 && s[len] == '=')
127      break;
128
129  if (s == 0)
130    {
131      if (i == e->allocated)
132	{
133	  e->allocated += 10;
134	  vector = (char **) xrealloc ((char *) vector,
135				       (e->allocated + 1) * sizeof (char *));
136	  e->vector = vector;
137	}
138      vector[i + 1] = 0;
139    }
140  else
141    xfree (s);
142
143  s = (char *) xmalloc (len + strlen (value) + 2);
144  strcpy (s, var);
145  strcat (s, "=");
146  strcat (s, value);
147  vector[i] = s;
148
149  /* This used to handle setting the PATH and GNUTARGET variables
150     specially.  The latter has been replaced by "set gnutarget"
151     (which has worked since GDB 4.11).  The former affects searching
152     the PATH to find SHELL, and searching the PATH to find the
153     argument of "symbol-file" or "exec-file".  Maybe we should have
154     some kind of "set exec-path" for that.  But in any event, having
155     "set env" affect anything besides the inferior is a bad idea.
156     What if we want to change the environment we pass to the program
157     without afecting GDB's behavior?  */
158
159  return;
160}
161
162/* Remove the setting for variable VAR from environment E.  */
163
164void
165unset_in_environ (struct environ *e, char *var)
166{
167  int len = strlen (var);
168  char **vector = e->vector;
169  char *s;
170
171  for (; (s = *vector) != NULL; vector++)
172    {
173      if (DEPRECATED_STREQN (s, var, len) && s[len] == '=')
174	{
175	  xfree (s);
176	  /* Walk through the vector, shuffling args down by one, including
177	     the NULL terminator.  Can't use memcpy() here since the regions
178	     overlap, and memmove() might not be available. */
179	  while ((vector[0] = vector[1]) != NULL)
180	    {
181	      vector++;
182	    }
183	  break;
184	}
185    }
186}
187