15796c8dcSSimon Schubert /* environ.c -- library for manipulating environments for GNU.
25796c8dcSSimon Schubert
3*ef5ccd6cSJohn Marino Copyright (C) 1986-2013 Free Software Foundation, Inc.
45796c8dcSSimon Schubert
55796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
65796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
75796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
85796c8dcSSimon Schubert (at your option) any later version.
95796c8dcSSimon Schubert
105796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
115796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
125796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
135796c8dcSSimon Schubert GNU General Public License for more details.
145796c8dcSSimon Schubert
155796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
165796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>. */
175796c8dcSSimon Schubert
185796c8dcSSimon Schubert #define min(a, b) ((a) < (b) ? (a) : (b))
195796c8dcSSimon Schubert #define max(a, b) ((a) > (b) ? (a) : (b))
205796c8dcSSimon Schubert
215796c8dcSSimon Schubert #include "defs.h"
225796c8dcSSimon Schubert #include "environ.h"
235796c8dcSSimon Schubert #include "gdb_string.h"
245796c8dcSSimon Schubert
255796c8dcSSimon Schubert
265796c8dcSSimon Schubert /* Return a new environment object. */
275796c8dcSSimon Schubert
285796c8dcSSimon Schubert struct gdb_environ *
make_environ(void)295796c8dcSSimon Schubert make_environ (void)
305796c8dcSSimon Schubert {
315796c8dcSSimon Schubert struct gdb_environ *e;
325796c8dcSSimon Schubert
335796c8dcSSimon Schubert e = (struct gdb_environ *) xmalloc (sizeof (struct gdb_environ));
345796c8dcSSimon Schubert
355796c8dcSSimon Schubert e->allocated = 10;
365796c8dcSSimon Schubert e->vector = (char **) xmalloc ((e->allocated + 1) * sizeof (char *));
375796c8dcSSimon Schubert e->vector[0] = 0;
385796c8dcSSimon Schubert return e;
395796c8dcSSimon Schubert }
405796c8dcSSimon Schubert
415796c8dcSSimon Schubert /* Free an environment and all the strings in it. */
425796c8dcSSimon Schubert
435796c8dcSSimon Schubert void
free_environ(struct gdb_environ * e)445796c8dcSSimon Schubert free_environ (struct gdb_environ *e)
455796c8dcSSimon Schubert {
465796c8dcSSimon Schubert char **vector = e->vector;
475796c8dcSSimon Schubert
485796c8dcSSimon Schubert while (*vector)
495796c8dcSSimon Schubert xfree (*vector++);
505796c8dcSSimon Schubert
515796c8dcSSimon Schubert xfree (e->vector);
525796c8dcSSimon Schubert xfree (e);
535796c8dcSSimon Schubert }
545796c8dcSSimon Schubert
555796c8dcSSimon Schubert /* Copy the environment given to this process into E.
565796c8dcSSimon Schubert Also copies all the strings in it, so we can be sure
575796c8dcSSimon Schubert that all strings in these environments are safe to free. */
585796c8dcSSimon Schubert
595796c8dcSSimon Schubert void
init_environ(struct gdb_environ * e)605796c8dcSSimon Schubert init_environ (struct gdb_environ *e)
615796c8dcSSimon Schubert {
625796c8dcSSimon Schubert extern char **environ;
635796c8dcSSimon Schubert int i;
645796c8dcSSimon Schubert
655796c8dcSSimon Schubert if (environ == NULL)
665796c8dcSSimon Schubert return;
675796c8dcSSimon Schubert
685796c8dcSSimon Schubert for (i = 0; environ[i]; i++) /*EMPTY */ ;
695796c8dcSSimon Schubert
705796c8dcSSimon Schubert if (e->allocated < i)
715796c8dcSSimon Schubert {
725796c8dcSSimon Schubert e->allocated = max (i, e->allocated + 10);
735796c8dcSSimon Schubert e->vector = (char **) xrealloc ((char *) e->vector,
745796c8dcSSimon Schubert (e->allocated + 1) * sizeof (char *));
755796c8dcSSimon Schubert }
765796c8dcSSimon Schubert
775796c8dcSSimon Schubert memcpy (e->vector, environ, (i + 1) * sizeof (char *));
785796c8dcSSimon Schubert
795796c8dcSSimon Schubert while (--i >= 0)
805796c8dcSSimon Schubert {
815796c8dcSSimon Schubert int len = strlen (e->vector[i]);
825796c8dcSSimon Schubert char *new = (char *) xmalloc (len + 1);
83cf7f2e2dSJohn Marino
845796c8dcSSimon Schubert memcpy (new, e->vector[i], len + 1);
855796c8dcSSimon Schubert e->vector[i] = new;
865796c8dcSSimon Schubert }
875796c8dcSSimon Schubert }
885796c8dcSSimon Schubert
895796c8dcSSimon Schubert /* Return the vector of environment E.
905796c8dcSSimon Schubert This is used to get something to pass to execve. */
915796c8dcSSimon Schubert
925796c8dcSSimon Schubert char **
environ_vector(struct gdb_environ * e)935796c8dcSSimon Schubert environ_vector (struct gdb_environ *e)
945796c8dcSSimon Schubert {
955796c8dcSSimon Schubert return e->vector;
965796c8dcSSimon Schubert }
975796c8dcSSimon Schubert
985796c8dcSSimon Schubert /* Return the value in environment E of variable VAR. */
995796c8dcSSimon Schubert
1005796c8dcSSimon Schubert char *
get_in_environ(const struct gdb_environ * e,const char * var)1015796c8dcSSimon Schubert get_in_environ (const struct gdb_environ *e, const char *var)
1025796c8dcSSimon Schubert {
1035796c8dcSSimon Schubert int len = strlen (var);
1045796c8dcSSimon Schubert char **vector = e->vector;
1055796c8dcSSimon Schubert char *s;
1065796c8dcSSimon Schubert
1075796c8dcSSimon Schubert for (; (s = *vector) != NULL; vector++)
1085796c8dcSSimon Schubert if (strncmp (s, var, len) == 0 && s[len] == '=')
1095796c8dcSSimon Schubert return &s[len + 1];
1105796c8dcSSimon Schubert
1115796c8dcSSimon Schubert return 0;
1125796c8dcSSimon Schubert }
1135796c8dcSSimon Schubert
1145796c8dcSSimon Schubert /* Store the value in E of VAR as VALUE. */
1155796c8dcSSimon Schubert
1165796c8dcSSimon Schubert void
set_in_environ(struct gdb_environ * e,const char * var,const char * value)1175796c8dcSSimon Schubert set_in_environ (struct gdb_environ *e, const char *var, const char *value)
1185796c8dcSSimon Schubert {
1195796c8dcSSimon Schubert int i;
1205796c8dcSSimon Schubert int len = strlen (var);
1215796c8dcSSimon Schubert char **vector = e->vector;
1225796c8dcSSimon Schubert char *s;
1235796c8dcSSimon Schubert
1245796c8dcSSimon Schubert for (i = 0; (s = vector[i]) != NULL; i++)
1255796c8dcSSimon Schubert if (strncmp (s, var, len) == 0 && s[len] == '=')
1265796c8dcSSimon Schubert break;
1275796c8dcSSimon Schubert
1285796c8dcSSimon Schubert if (s == 0)
1295796c8dcSSimon Schubert {
1305796c8dcSSimon Schubert if (i == e->allocated)
1315796c8dcSSimon Schubert {
1325796c8dcSSimon Schubert e->allocated += 10;
1335796c8dcSSimon Schubert vector = (char **) xrealloc ((char *) vector,
1345796c8dcSSimon Schubert (e->allocated + 1) * sizeof (char *));
1355796c8dcSSimon Schubert e->vector = vector;
1365796c8dcSSimon Schubert }
1375796c8dcSSimon Schubert vector[i + 1] = 0;
1385796c8dcSSimon Schubert }
1395796c8dcSSimon Schubert else
1405796c8dcSSimon Schubert xfree (s);
1415796c8dcSSimon Schubert
1425796c8dcSSimon Schubert s = (char *) xmalloc (len + strlen (value) + 2);
1435796c8dcSSimon Schubert strcpy (s, var);
1445796c8dcSSimon Schubert strcat (s, "=");
1455796c8dcSSimon Schubert strcat (s, value);
1465796c8dcSSimon Schubert vector[i] = s;
1475796c8dcSSimon Schubert
1485796c8dcSSimon Schubert /* This used to handle setting the PATH and GNUTARGET variables
1495796c8dcSSimon Schubert specially. The latter has been replaced by "set gnutarget"
1505796c8dcSSimon Schubert (which has worked since GDB 4.11). The former affects searching
1515796c8dcSSimon Schubert the PATH to find SHELL, and searching the PATH to find the
1525796c8dcSSimon Schubert argument of "symbol-file" or "exec-file". Maybe we should have
1535796c8dcSSimon Schubert some kind of "set exec-path" for that. But in any event, having
1545796c8dcSSimon Schubert "set env" affect anything besides the inferior is a bad idea.
1555796c8dcSSimon Schubert What if we want to change the environment we pass to the program
1565796c8dcSSimon Schubert without afecting GDB's behavior? */
1575796c8dcSSimon Schubert
1585796c8dcSSimon Schubert return;
1595796c8dcSSimon Schubert }
1605796c8dcSSimon Schubert
1615796c8dcSSimon Schubert /* Remove the setting for variable VAR from environment E. */
1625796c8dcSSimon Schubert
1635796c8dcSSimon Schubert void
unset_in_environ(struct gdb_environ * e,char * var)1645796c8dcSSimon Schubert unset_in_environ (struct gdb_environ *e, char *var)
1655796c8dcSSimon Schubert {
1665796c8dcSSimon Schubert int len = strlen (var);
1675796c8dcSSimon Schubert char **vector = e->vector;
1685796c8dcSSimon Schubert char *s;
1695796c8dcSSimon Schubert
1705796c8dcSSimon Schubert for (; (s = *vector) != NULL; vector++)
1715796c8dcSSimon Schubert {
1725796c8dcSSimon Schubert if (strncmp (s, var, len) == 0 && s[len] == '=')
1735796c8dcSSimon Schubert {
1745796c8dcSSimon Schubert xfree (s);
1755796c8dcSSimon Schubert /* Walk through the vector, shuffling args down by one, including
1765796c8dcSSimon Schubert the NULL terminator. Can't use memcpy() here since the regions
1775796c8dcSSimon Schubert overlap, and memmove() might not be available. */
1785796c8dcSSimon Schubert while ((vector[0] = vector[1]) != NULL)
1795796c8dcSSimon Schubert {
1805796c8dcSSimon Schubert vector++;
1815796c8dcSSimon Schubert }
1825796c8dcSSimon Schubert break;
1835796c8dcSSimon Schubert }
1845796c8dcSSimon Schubert }
1855796c8dcSSimon Schubert }
186