aboutsummaryrefslogtreecommitdiff
path: root/gdbsupport/environ.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdbsupport/environ.c')
-rw-r--r--gdbsupport/environ.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/gdbsupport/environ.c b/gdbsupport/environ.c
new file mode 100644
index 0000000..55d0a74
--- /dev/null
+++ b/gdbsupport/environ.c
@@ -0,0 +1,183 @@
+/* environ.c -- library for manipulating environments for GNU.
+
+ Copyright (C) 1986-2020 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "common-defs.h"
+#include "environ.h"
+#include <algorithm>
+#include <utility>
+
+/* See gdbsupport/environ.h. */
+
+gdb_environ &
+gdb_environ::operator= (gdb_environ &&e)
+{
+ /* Are we self-moving? */
+ if (&e == this)
+ return *this;
+
+ m_environ_vector = std::move (e.m_environ_vector);
+ m_user_set_env = std::move (e.m_user_set_env);
+ m_user_unset_env = std::move (e.m_user_unset_env);
+ e.m_environ_vector.clear ();
+ e.m_environ_vector.push_back (NULL);
+ e.m_user_set_env.clear ();
+ e.m_user_unset_env.clear ();
+ return *this;
+}
+
+/* See gdbsupport/environ.h. */
+
+gdb_environ gdb_environ::from_host_environ ()
+{
+ extern char **environ;
+ gdb_environ e;
+
+ if (environ == NULL)
+ return e;
+
+ for (int i = 0; environ[i] != NULL; ++i)
+ {
+ /* Make sure we add the element before the last (NULL). */
+ e.m_environ_vector.insert (e.m_environ_vector.end () - 1,
+ xstrdup (environ[i]));
+ }
+
+ return e;
+}
+
+/* See gdbsupport/environ.h. */
+
+void
+gdb_environ::clear ()
+{
+ for (char *v : m_environ_vector)
+ xfree (v);
+ m_environ_vector.clear ();
+ /* Always add the NULL element. */
+ m_environ_vector.push_back (NULL);
+ m_user_set_env.clear ();
+ m_user_unset_env.clear ();
+}
+
+/* Helper function to check if STRING contains an environment variable
+ assignment of VAR, i.e., if STRING starts with 'VAR='. Return true
+ if it contains, false otherwise. */
+
+static bool
+match_var_in_string (const char *string, const char *var, size_t var_len)
+{
+ if (strncmp (string, var, var_len) == 0 && string[var_len] == '=')
+ return true;
+
+ return false;
+}
+
+/* See gdbsupport/environ.h. */
+
+const char *
+gdb_environ::get (const char *var) const
+{
+ size_t len = strlen (var);
+
+ for (char *el : m_environ_vector)
+ if (el != NULL && match_var_in_string (el, var, len))
+ return &el[len + 1];
+
+ return NULL;
+}
+
+/* See gdbsupport/environ.h. */
+
+void
+gdb_environ::set (const char *var, const char *value)
+{
+ char *fullvar = concat (var, "=", value, NULL);
+
+ /* We have to unset the variable in the vector if it exists. */
+ unset (var, false);
+
+ /* Insert the element before the last one, which is always NULL. */
+ m_environ_vector.insert (m_environ_vector.end () - 1, fullvar);
+
+ /* Mark this environment variable as having been set by the user.
+ This will be useful when we deal with setting environment
+ variables on the remote target. */
+ m_user_set_env.insert (std::string (fullvar));
+
+ /* If this environment variable is marked as unset by the user, then
+ remove it from the list, because now the user wants to set
+ it. */
+ m_user_unset_env.erase (std::string (var));
+}
+
+/* See gdbsupport/environ.h. */
+
+void
+gdb_environ::unset (const char *var, bool update_unset_list)
+{
+ size_t len = strlen (var);
+ std::vector<char *>::iterator it_env;
+
+ /* We iterate until '.end () - 1' because the last element is
+ always NULL. */
+ for (it_env = m_environ_vector.begin ();
+ it_env != m_environ_vector.end () - 1;
+ ++it_env)
+ if (match_var_in_string (*it_env, var, len))
+ break;
+
+ if (it_env != m_environ_vector.end () - 1)
+ {
+ m_user_set_env.erase (std::string (*it_env));
+ xfree (*it_env);
+
+ m_environ_vector.erase (it_env);
+ }
+
+ if (update_unset_list)
+ m_user_unset_env.insert (std::string (var));
+}
+
+/* See gdbsupport/environ.h. */
+
+void
+gdb_environ::unset (const char *var)
+{
+ unset (var, true);
+}
+
+/* See gdbsupport/environ.h. */
+
+char **
+gdb_environ::envp () const
+{
+ return const_cast<char **> (&m_environ_vector[0]);
+}
+
+/* See gdbsupport/environ.h. */
+
+const std::set<std::string> &
+gdb_environ::user_set_env () const
+{
+ return m_user_set_env;
+}
+
+const std::set<std::string> &
+gdb_environ::user_unset_env () const
+{
+ return m_user_unset_env;
+}