environ.c revision 98944
119370Spst/* environ.c -- library for manipulating environments for GNU.
298944Sobrien   Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 2000
398944Sobrien   Free Software Foundation, Inc.
419370Spst
598944Sobrien   This program is free software; you can redistribute it and/or modify
698944Sobrien   it under the terms of the GNU General Public License as published by
798944Sobrien   the Free Software Foundation; either version 2 of the License, or
898944Sobrien   (at your option) any later version.
919370Spst
1098944Sobrien   This program is distributed in the hope that it will be useful,
1198944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1298944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1398944Sobrien   GNU General Public License for more details.
1419370Spst
1598944Sobrien   You should have received a copy of the GNU General Public License
1698944Sobrien   along with this program; if not, write to the Free Software
1798944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
1898944Sobrien   Boston, MA 02111-1307, USA.  */
1919370Spst
2019370Spst#define min(a, b) ((a) < (b) ? (a) : (b))
2119370Spst#define max(a, b) ((a) > (b) ? (a) : (b))
2219370Spst
2319370Spst#include "defs.h"
2419370Spst#include "environ.h"
2519370Spst#include "gdb_string.h"
2698944Sobrien
2719370Spst
2819370Spst/* Return a new environment object.  */
2919370Spst
3019370Spststruct environ *
3198944Sobrienmake_environ (void)
3219370Spst{
3319370Spst  register struct environ *e;
3419370Spst
3519370Spst  e = (struct environ *) xmalloc (sizeof (struct environ));
3619370Spst
3719370Spst  e->allocated = 10;
3819370Spst  e->vector = (char **) xmalloc ((e->allocated + 1) * sizeof (char *));
3919370Spst  e->vector[0] = 0;
4019370Spst  return e;
4119370Spst}
4219370Spst
4319370Spst/* Free an environment and all the strings in it.  */
4419370Spst
4519370Spstvoid
4698944Sobrienfree_environ (register struct environ *e)
4719370Spst{
4819370Spst  register char **vector = e->vector;
4919370Spst
5019370Spst  while (*vector)
5198944Sobrien    xfree (*vector++);
5219370Spst
5398944Sobrien  xfree (e);
5419370Spst}
5519370Spst
5619370Spst/* Copy the environment given to this process into E.
5719370Spst   Also copies all the strings in it, so we can be sure
5819370Spst   that all strings in these environments are safe to free.  */
5919370Spst
6019370Spstvoid
6198944Sobrieninit_environ (register struct environ *e)
6219370Spst{
6319370Spst  extern char **environ;
6419370Spst  register int i;
6519370Spst
6619370Spst  if (environ == NULL)
6719370Spst    return;
6819370Spst
6998944Sobrien  for (i = 0; environ[i]; i++) /*EMPTY */ ;
7019370Spst
7119370Spst  if (e->allocated < i)
7219370Spst    {
7319370Spst      e->allocated = max (i, e->allocated + 10);
7498944Sobrien      e->vector = (char **) xrealloc ((char *) e->vector,
7519370Spst				      (e->allocated + 1) * sizeof (char *));
7619370Spst    }
7719370Spst
7819370Spst  memcpy (e->vector, environ, (i + 1) * sizeof (char *));
7919370Spst
8019370Spst  while (--i >= 0)
8119370Spst    {
8219370Spst      register int len = strlen (e->vector[i]);
8319370Spst      register char *new = (char *) xmalloc (len + 1);
8419370Spst      memcpy (new, e->vector[i], len + 1);
8519370Spst      e->vector[i] = new;
8619370Spst    }
8719370Spst}
8819370Spst
8919370Spst/* Return the vector of environment E.
9019370Spst   This is used to get something to pass to execve.  */
9119370Spst
9219370Spstchar **
9398944Sobrienenviron_vector (struct environ *e)
9419370Spst{
9519370Spst  return e->vector;
9619370Spst}
9719370Spst
9819370Spst/* Return the value in environment E of variable VAR.  */
9919370Spst
10019370Spstchar *
10198944Sobrienget_in_environ (const struct environ *e, const char *var)
10219370Spst{
10319370Spst  register int len = strlen (var);
10419370Spst  register char **vector = e->vector;
10519370Spst  register char *s;
10619370Spst
10719370Spst  for (; (s = *vector) != NULL; vector++)
10819370Spst    if (STREQN (s, var, len) && s[len] == '=')
10919370Spst      return &s[len + 1];
11019370Spst
11119370Spst  return 0;
11219370Spst}
11319370Spst
11419370Spst/* Store the value in E of VAR as VALUE.  */
11519370Spst
11619370Spstvoid
11798944Sobrienset_in_environ (struct environ *e, const char *var, const char *value)
11819370Spst{
11919370Spst  register int i;
12019370Spst  register int len = strlen (var);
12119370Spst  register char **vector = e->vector;
12219370Spst  register char *s;
12319370Spst
12419370Spst  for (i = 0; (s = vector[i]) != NULL; i++)
12519370Spst    if (STREQN (s, var, len) && s[len] == '=')
12619370Spst      break;
12719370Spst
12819370Spst  if (s == 0)
12919370Spst    {
13019370Spst      if (i == e->allocated)
13119370Spst	{
13219370Spst	  e->allocated += 10;
13398944Sobrien	  vector = (char **) xrealloc ((char *) vector,
13419370Spst				       (e->allocated + 1) * sizeof (char *));
13519370Spst	  e->vector = vector;
13619370Spst	}
13719370Spst      vector[i + 1] = 0;
13819370Spst    }
13919370Spst  else
14098944Sobrien    xfree (s);
14119370Spst
14219370Spst  s = (char *) xmalloc (len + strlen (value) + 2);
14319370Spst  strcpy (s, var);
14419370Spst  strcat (s, "=");
14519370Spst  strcat (s, value);
14619370Spst  vector[i] = s;
14719370Spst
14819370Spst  /* This used to handle setting the PATH and GNUTARGET variables
14919370Spst     specially.  The latter has been replaced by "set gnutarget"
15019370Spst     (which has worked since GDB 4.11).  The former affects searching
15119370Spst     the PATH to find SHELL, and searching the PATH to find the
15219370Spst     argument of "symbol-file" or "exec-file".  Maybe we should have
15319370Spst     some kind of "set exec-path" for that.  But in any event, having
15419370Spst     "set env" affect anything besides the inferior is a bad idea.
15519370Spst     What if we want to change the environment we pass to the program
15619370Spst     without afecting GDB's behavior?  */
15719370Spst
15819370Spst  return;
15919370Spst}
16019370Spst
16119370Spst/* Remove the setting for variable VAR from environment E.  */
16219370Spst
16319370Spstvoid
16498944Sobrienunset_in_environ (struct environ *e, char *var)
16519370Spst{
16619370Spst  register int len = strlen (var);
16719370Spst  register char **vector = e->vector;
16819370Spst  register char *s;
16919370Spst
17019370Spst  for (; (s = *vector) != NULL; vector++)
17119370Spst    {
17219370Spst      if (STREQN (s, var, len) && s[len] == '=')
17319370Spst	{
17498944Sobrien	  xfree (s);
17519370Spst	  /* Walk through the vector, shuffling args down by one, including
17619370Spst	     the NULL terminator.  Can't use memcpy() here since the regions
17719370Spst	     overlap, and memmove() might not be available. */
17819370Spst	  while ((vector[0] = vector[1]) != NULL)
17919370Spst	    {
18019370Spst	      vector++;
18119370Spst	    }
18219370Spst	  break;
18319370Spst	}
18419370Spst    }
18519370Spst}
186