aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--env.cpp28
-rw-r--r--tests/test3.in6
-rw-r--r--tests/test3.out1
3 files changed, 17 insertions, 18 deletions
diff --git a/env.cpp b/env.cpp
index 5fcaecde..fc10e820 100644
--- a/env.cpp
+++ b/env.cpp
@@ -415,17 +415,10 @@ wcstring env_get_pwd_slash(void)
return pwd;
}
-// Some variables should not be arrays. This used to be handled by a startup script, but we'd like to get down to 0 forks for startup, so handle it here.
-static bool variable_can_be_array(const wcstring &key)
+/* Here is the whitelist of variables that we colon-delimit, both incoming from the environment and outgoing back to it. This is deliberately very short - we don't want to add language-specific values like CLASSPATH. */
+static bool variable_is_colon_delimited_array(const wcstring &str)
{
- if (key == L"DISPLAY")
- {
- return false;
- }
- else
- {
- return true;
- }
+ return contains(str, L"PATH", L"MANPATH", L"CDPATH");
}
void env_init(const struct config_paths_t *paths /* or NULL */)
@@ -487,7 +480,7 @@ void env_init(const struct config_paths_t *paths /* or NULL */)
wcstring key = key_and_val.substr(0, eql);
if (is_read_only(key) || is_electric(key)) continue;
wcstring val = key_and_val.substr(eql + 1);
- if (variable_can_be_array(key))
+ if (variable_is_colon_delimited_array(key))
{
std::replace(val.begin(), val.end(), L':', ARRAY_SEP);
}
@@ -1293,19 +1286,22 @@ static void get_exported(const env_node_t *n, std::map<wcstring, wcstring> &h)
}
}
+/* Given a map from key to value, add values to out of the form key=value */
static void export_func(const std::map<wcstring, wcstring> &envs, std::vector<std::string> &out)
{
+ out.reserve(out.size() + envs.size());
std::map<wcstring, wcstring>::const_iterator iter;
for (iter = envs.begin(); iter != envs.end(); ++iter)
{
- const std::string ks = wcs2string(iter->first);
+ const wcstring &key = iter->first;
+ const std::string &ks = wcs2string(key);
std::string vs = wcs2string(iter->second);
- for (size_t i=0; i < vs.size(); i++)
+ /* Arrays in the value are ASCII record separator (0x1e) delimited. But some variables should have colons. Add those. */
+ if (variable_is_colon_delimited_array(key))
{
- char &vc = vs.at(i);
- if (vc == ARRAY_SEP)
- vc = ':';
+ /* Replace ARRAY_SEP with colon */
+ std::replace(vs.begin(), vs.end(), (char)ARRAY_SEP, ':');
}
/* Put a string on the vector */
diff --git a/tests/test3.in b/tests/test3.in
index 4dec9a83..b162939d 100644
--- a/tests/test3.in
+++ b/tests/test3.in
@@ -248,7 +248,9 @@ env SHLVL=" 3" ../fish -c 'echo SHLVL: $SHLVL'
env DISPLAY="localhost:0.0" ../fish -c 'echo Elements in DISPLAY: (count $DISPLAY)'
# We can't use PATH for this because the global configuration will modify PATH
# based on /etc/paths and /etc/paths.d.
-# At the moment, most variables split on :. So we can use an arbitrary variable for this.
-env FOO="one:two:three:four" ../fish -c 'echo Elements in FOO: (count $FOO)'
+# Exported arrays should use record separator, with a few exceptions. So we can use an arbitrary variable for this.
+env FOO=one\x1etwo\x1ethree\x1efour ../fish -c 'echo Elements in FOO: (count $FOO)'
+# some must use colon separators!
+set -lx MANPATH man1 man2 man3 ; env | grep MANPATH
true
diff --git a/tests/test3.out b/tests/test3.out
index 5d3a48b2..d7dd2c43 100644
--- a/tests/test3.out
+++ b/tests/test3.out
@@ -30,3 +30,4 @@ SHLVL: 4
SHLVL: 4
Elements in DISPLAY: 1
Elements in FOO: 4
+MANPATH=man1:man2:man3