18dffb485Schristos /* environ.c -- library for manipulating environments for GNU. 28dffb485Schristos 3*5ba1f45fSchristos Copyright (C) 1986-2024 Free Software Foundation, Inc. 48dffb485Schristos 58dffb485Schristos This program is free software; you can redistribute it and/or modify 68dffb485Schristos it under the terms of the GNU General Public License as published by 78dffb485Schristos the Free Software Foundation; either version 3 of the License, or 88dffb485Schristos (at your option) any later version. 98dffb485Schristos 108dffb485Schristos This program is distributed in the hope that it will be useful, 118dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 128dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 138dffb485Schristos GNU General Public License for more details. 148dffb485Schristos 158dffb485Schristos You should have received a copy of the GNU General Public License 168dffb485Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 178dffb485Schristos 188dffb485Schristos #include "environ.h" 198dffb485Schristos #include <algorithm> 208dffb485Schristos #include <utility> 218dffb485Schristos 228dffb485Schristos /* See gdbsupport/environ.h. */ 238dffb485Schristos 248dffb485Schristos gdb_environ & 258dffb485Schristos gdb_environ::operator= (gdb_environ &&e) 268dffb485Schristos { 278dffb485Schristos /* Are we self-moving? */ 288dffb485Schristos if (&e == this) 298dffb485Schristos return *this; 308dffb485Schristos 314b169a6bSchristos this->clear (); 324b169a6bSchristos 338dffb485Schristos m_environ_vector = std::move (e.m_environ_vector); 348dffb485Schristos m_user_set_env = std::move (e.m_user_set_env); 358dffb485Schristos m_user_unset_env = std::move (e.m_user_unset_env); 368dffb485Schristos e.m_environ_vector.clear (); 378dffb485Schristos e.m_environ_vector.push_back (NULL); 388dffb485Schristos e.m_user_set_env.clear (); 398dffb485Schristos e.m_user_unset_env.clear (); 408dffb485Schristos return *this; 418dffb485Schristos } 428dffb485Schristos 438dffb485Schristos /* See gdbsupport/environ.h. */ 448dffb485Schristos 458dffb485Schristos gdb_environ gdb_environ::from_host_environ () 468dffb485Schristos { 478dffb485Schristos extern char **environ; 488dffb485Schristos gdb_environ e; 498dffb485Schristos 508dffb485Schristos if (environ == NULL) 518dffb485Schristos return e; 528dffb485Schristos 538dffb485Schristos for (int i = 0; environ[i] != NULL; ++i) 548dffb485Schristos { 558dffb485Schristos /* Make sure we add the element before the last (NULL). */ 568dffb485Schristos e.m_environ_vector.insert (e.m_environ_vector.end () - 1, 578dffb485Schristos xstrdup (environ[i])); 588dffb485Schristos } 598dffb485Schristos 608dffb485Schristos return e; 618dffb485Schristos } 628dffb485Schristos 638dffb485Schristos /* See gdbsupport/environ.h. */ 648dffb485Schristos 658dffb485Schristos void 668dffb485Schristos gdb_environ::clear () 678dffb485Schristos { 688dffb485Schristos for (char *v : m_environ_vector) 698dffb485Schristos xfree (v); 708dffb485Schristos m_environ_vector.clear (); 718dffb485Schristos /* Always add the NULL element. */ 728dffb485Schristos m_environ_vector.push_back (NULL); 738dffb485Schristos m_user_set_env.clear (); 748dffb485Schristos m_user_unset_env.clear (); 758dffb485Schristos } 768dffb485Schristos 778dffb485Schristos /* Helper function to check if STRING contains an environment variable 788dffb485Schristos assignment of VAR, i.e., if STRING starts with 'VAR='. Return true 798dffb485Schristos if it contains, false otherwise. */ 808dffb485Schristos 818dffb485Schristos static bool 828dffb485Schristos match_var_in_string (const char *string, const char *var, size_t var_len) 838dffb485Schristos { 848dffb485Schristos if (strncmp (string, var, var_len) == 0 && string[var_len] == '=') 858dffb485Schristos return true; 868dffb485Schristos 878dffb485Schristos return false; 888dffb485Schristos } 898dffb485Schristos 908dffb485Schristos /* See gdbsupport/environ.h. */ 918dffb485Schristos 928dffb485Schristos const char * 938dffb485Schristos gdb_environ::get (const char *var) const 948dffb485Schristos { 958dffb485Schristos size_t len = strlen (var); 968dffb485Schristos 978dffb485Schristos for (char *el : m_environ_vector) 988dffb485Schristos if (el != NULL && match_var_in_string (el, var, len)) 998dffb485Schristos return &el[len + 1]; 1008dffb485Schristos 1018dffb485Schristos return NULL; 1028dffb485Schristos } 1038dffb485Schristos 1048dffb485Schristos /* See gdbsupport/environ.h. */ 1058dffb485Schristos 1068dffb485Schristos void 1078dffb485Schristos gdb_environ::set (const char *var, const char *value) 1088dffb485Schristos { 1098dffb485Schristos char *fullvar = concat (var, "=", value, (char *) NULL); 1108dffb485Schristos 1118dffb485Schristos /* We have to unset the variable in the vector if it exists. */ 1128dffb485Schristos unset (var, false); 1138dffb485Schristos 1148dffb485Schristos /* Insert the element before the last one, which is always NULL. */ 1158dffb485Schristos m_environ_vector.insert (m_environ_vector.end () - 1, fullvar); 1168dffb485Schristos 1178dffb485Schristos /* Mark this environment variable as having been set by the user. 1188dffb485Schristos This will be useful when we deal with setting environment 1198dffb485Schristos variables on the remote target. */ 1208dffb485Schristos m_user_set_env.insert (std::string (fullvar)); 1218dffb485Schristos 1228dffb485Schristos /* If this environment variable is marked as unset by the user, then 1238dffb485Schristos remove it from the list, because now the user wants to set 1248dffb485Schristos it. */ 1258dffb485Schristos m_user_unset_env.erase (std::string (var)); 1268dffb485Schristos } 1278dffb485Schristos 1288dffb485Schristos /* See gdbsupport/environ.h. */ 1298dffb485Schristos 1308dffb485Schristos void 1318dffb485Schristos gdb_environ::unset (const char *var, bool update_unset_list) 1328dffb485Schristos { 1338dffb485Schristos size_t len = strlen (var); 1348dffb485Schristos std::vector<char *>::iterator it_env; 1358dffb485Schristos 1368dffb485Schristos /* We iterate until '.end () - 1' because the last element is 1378dffb485Schristos always NULL. */ 1388dffb485Schristos for (it_env = m_environ_vector.begin (); 1398dffb485Schristos it_env != m_environ_vector.end () - 1; 1408dffb485Schristos ++it_env) 1418dffb485Schristos if (match_var_in_string (*it_env, var, len)) 1428dffb485Schristos break; 1438dffb485Schristos 1448dffb485Schristos if (it_env != m_environ_vector.end () - 1) 1458dffb485Schristos { 1468dffb485Schristos m_user_set_env.erase (std::string (*it_env)); 1478dffb485Schristos xfree (*it_env); 1488dffb485Schristos 1498dffb485Schristos m_environ_vector.erase (it_env); 1508dffb485Schristos } 1518dffb485Schristos 1528dffb485Schristos if (update_unset_list) 1538dffb485Schristos m_user_unset_env.insert (std::string (var)); 1548dffb485Schristos } 1558dffb485Schristos 1568dffb485Schristos /* See gdbsupport/environ.h. */ 1578dffb485Schristos 1588dffb485Schristos void 1598dffb485Schristos gdb_environ::unset (const char *var) 1608dffb485Schristos { 1618dffb485Schristos unset (var, true); 1628dffb485Schristos } 1638dffb485Schristos 1648dffb485Schristos /* See gdbsupport/environ.h. */ 1658dffb485Schristos 1668dffb485Schristos char ** 1678dffb485Schristos gdb_environ::envp () const 1688dffb485Schristos { 1698dffb485Schristos return const_cast<char **> (&m_environ_vector[0]); 1708dffb485Schristos } 1718dffb485Schristos 1728dffb485Schristos /* See gdbsupport/environ.h. */ 1738dffb485Schristos 1748dffb485Schristos const std::set<std::string> & 1758dffb485Schristos gdb_environ::user_set_env () const 1768dffb485Schristos { 1778dffb485Schristos return m_user_set_env; 1788dffb485Schristos } 1798dffb485Schristos 1808dffb485Schristos const std::set<std::string> & 1818dffb485Schristos gdb_environ::user_unset_env () const 1828dffb485Schristos { 1838dffb485Schristos return m_user_unset_env; 1848dffb485Schristos } 185