119370Spst/* environ.c -- library for manipulating environments for GNU.
219370Spst
3130803Smarcel   Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 2000,
4130803Smarcel   2003 Free Software Foundation, Inc.
5130803Smarcel
698944Sobrien   This program is free software; you can redistribute it and/or modify
798944Sobrien   it under the terms of the GNU General Public License as published by
898944Sobrien   the Free Software Foundation; either version 2 of the License, or
998944Sobrien   (at your option) any later version.
1019370Spst
1198944Sobrien   This program is distributed in the hope that it will be useful,
1298944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1398944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1498944Sobrien   GNU General Public License for more details.
1519370Spst
1698944Sobrien   You should have received a copy of the GNU General Public License
1798944Sobrien   along with this program; if not, write to the Free Software
1898944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
1998944Sobrien   Boston, MA 02111-1307, USA.  */
2019370Spst
2119370Spst#define min(a, b) ((a) < (b) ? (a) : (b))
2219370Spst#define max(a, b) ((a) > (b) ? (a) : (b))
2319370Spst
2419370Spst#include "defs.h"
2519370Spst#include "environ.h"
2619370Spst#include "gdb_string.h"
2798944Sobrien
2819370Spst
2919370Spst/* Return a new environment object.  */
3019370Spst
3119370Spststruct environ *
3298944Sobrienmake_environ (void)
3319370Spst{
34130803Smarcel  struct environ *e;
3519370Spst
3619370Spst  e = (struct environ *) xmalloc (sizeof (struct environ));
3719370Spst
3819370Spst  e->allocated = 10;
3919370Spst  e->vector = (char **) xmalloc ((e->allocated + 1) * sizeof (char *));
4019370Spst  e->vector[0] = 0;
4119370Spst  return e;
4219370Spst}
4319370Spst
4419370Spst/* Free an environment and all the strings in it.  */
4519370Spst
4619370Spstvoid
47130803Smarcelfree_environ (struct environ *e)
4819370Spst{
49130803Smarcel  char **vector = e->vector;
5019370Spst
5119370Spst  while (*vector)
5298944Sobrien    xfree (*vector++);
5319370Spst
5498944Sobrien  xfree (e);
5519370Spst}
5619370Spst
5719370Spst/* Copy the environment given to this process into E.
5819370Spst   Also copies all the strings in it, so we can be sure
5919370Spst   that all strings in these environments are safe to free.  */
6019370Spst
6119370Spstvoid
62130803Smarcelinit_environ (struct environ *e)
6319370Spst{
6419370Spst  extern char **environ;
65130803Smarcel  int i;
6619370Spst
6719370Spst  if (environ == NULL)
6819370Spst    return;
6919370Spst
7098944Sobrien  for (i = 0; environ[i]; i++) /*EMPTY */ ;
7119370Spst
7219370Spst  if (e->allocated < i)
7319370Spst    {
7419370Spst      e->allocated = max (i, e->allocated + 10);
7598944Sobrien      e->vector = (char **) xrealloc ((char *) e->vector,
7619370Spst				      (e->allocated + 1) * sizeof (char *));
7719370Spst    }
7819370Spst
7919370Spst  memcpy (e->vector, environ, (i + 1) * sizeof (char *));
8019370Spst
8119370Spst  while (--i >= 0)
8219370Spst    {
83130803Smarcel      int len = strlen (e->vector[i]);
84130803Smarcel      char *new = (char *) xmalloc (len + 1);
8519370Spst      memcpy (new, e->vector[i], len + 1);
8619370Spst      e->vector[i] = new;
8719370Spst    }
8819370Spst}
8919370Spst
9019370Spst/* Return the vector of environment E.
9119370Spst   This is used to get something to pass to execve.  */
9219370Spst
9319370Spstchar **
9498944Sobrienenviron_vector (struct environ *e)
9519370Spst{
9619370Spst  return e->vector;
9719370Spst}
9819370Spst
9919370Spst/* Return the value in environment E of variable VAR.  */
10019370Spst
10119370Spstchar *
10298944Sobrienget_in_environ (const struct environ *e, const char *var)
10319370Spst{
104130803Smarcel  int len = strlen (var);
105130803Smarcel  char **vector = e->vector;
106130803Smarcel  char *s;
10719370Spst
10819370Spst  for (; (s = *vector) != NULL; vector++)
109130803Smarcel    if (strncmp (s, var, len) == 0 && s[len] == '=')
11019370Spst      return &s[len + 1];
11119370Spst
11219370Spst  return 0;
11319370Spst}
11419370Spst
11519370Spst/* Store the value in E of VAR as VALUE.  */
11619370Spst
11719370Spstvoid
11898944Sobrienset_in_environ (struct environ *e, const char *var, const char *value)
11919370Spst{
120130803Smarcel  int i;
121130803Smarcel  int len = strlen (var);
122130803Smarcel  char **vector = e->vector;
123130803Smarcel  char *s;
12419370Spst
12519370Spst  for (i = 0; (s = vector[i]) != NULL; i++)
126130803Smarcel    if (strncmp (s, var, len) == 0 && s[len] == '=')
12719370Spst      break;
12819370Spst
12919370Spst  if (s == 0)
13019370Spst    {
13119370Spst      if (i == e->allocated)
13219370Spst	{
13319370Spst	  e->allocated += 10;
13498944Sobrien	  vector = (char **) xrealloc ((char *) vector,
13519370Spst				       (e->allocated + 1) * sizeof (char *));
13619370Spst	  e->vector = vector;
13719370Spst	}
13819370Spst      vector[i + 1] = 0;
13919370Spst    }
14019370Spst  else
14198944Sobrien    xfree (s);
14219370Spst
14319370Spst  s = (char *) xmalloc (len + strlen (value) + 2);
14419370Spst  strcpy (s, var);
14519370Spst  strcat (s, "=");
14619370Spst  strcat (s, value);
14719370Spst  vector[i] = s;
14819370Spst
14919370Spst  /* This used to handle setting the PATH and GNUTARGET variables
15019370Spst     specially.  The latter has been replaced by "set gnutarget"
15119370Spst     (which has worked since GDB 4.11).  The former affects searching
15219370Spst     the PATH to find SHELL, and searching the PATH to find the
15319370Spst     argument of "symbol-file" or "exec-file".  Maybe we should have
15419370Spst     some kind of "set exec-path" for that.  But in any event, having
15519370Spst     "set env" affect anything besides the inferior is a bad idea.
15619370Spst     What if we want to change the environment we pass to the program
15719370Spst     without afecting GDB's behavior?  */
15819370Spst
15919370Spst  return;
16019370Spst}
16119370Spst
16219370Spst/* Remove the setting for variable VAR from environment E.  */
16319370Spst
16419370Spstvoid
16598944Sobrienunset_in_environ (struct environ *e, char *var)
16619370Spst{
167130803Smarcel  int len = strlen (var);
168130803Smarcel  char **vector = e->vector;
169130803Smarcel  char *s;
17019370Spst
17119370Spst  for (; (s = *vector) != NULL; vector++)
17219370Spst    {
173130803Smarcel      if (DEPRECATED_STREQN (s, var, len) && s[len] == '=')
17419370Spst	{
17598944Sobrien	  xfree (s);
17619370Spst	  /* Walk through the vector, shuffling args down by one, including
17719370Spst	     the NULL terminator.  Can't use memcpy() here since the regions
17819370Spst	     overlap, and memmove() might not be available. */
17919370Spst	  while ((vector[0] = vector[1]) != NULL)
18019370Spst	    {
18119370Spst	      vector++;
18219370Spst	    }
18319370Spst	  break;
18419370Spst	}
18519370Spst    }
18619370Spst}
187