@@ -66,10 +66,41 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
6666
6767 // WSLENV is a colon-delimited list of environment variables (+flags) that should appear inside WSL
6868 // https://devblogs.microsoft.com/commandline/share-environment-vars-between-wsl-and-windows/
69- std::wstring wslEnv{ L" WT_SESSION:WT_PROFILE_ID:" };
69+
70+ // WSLENV.1: Get a handle to the WSLENV environment variable.
71+ auto & wslEnv = environment.as_map ()[L" WSLENV" ];
72+ std::wstring additionalWslEnv;
73+
74+ // WSLENV.2: Figure out what variables are already in WSLENV.
75+ std::unordered_set<std::wstring_view> wslEnvVars;
76+ for (const auto & part : til::split_iterator{ std::wstring_view{ wslEnv }, L' :' })
77+ {
78+ // Each part may contain a variable name and flags (e.g., /p, /l, etc.)
79+ // We only care about the variable name for WSLENV.
80+ const auto key = til::safe_slice_len (part, 0 , part.rfind (L' /' ));
81+ wslEnvVars.emplace (key);
82+ }
83+
84+ // WSLENV.3: Add our terminal-specific environment variables to WSLENV.
85+ static constexpr std::wstring_view builtinWslEnvVars[] = {
86+ L" WT_SESSION" ,
87+ L" WT_PROFILE_ID" ,
88+ };
89+ // Misdiagnosis in MSVC 14.44.35207. No pointer arithmetic in sight.
90+ #pragma warning(suppress : 26481) // Don't use pointer arithmetic. Use span instead (bounds.1).
91+ for (const auto & key : builtinWslEnvVars)
92+ {
93+ if (wslEnvVars.emplace (key).second )
94+ {
95+ additionalWslEnv.append (key);
96+ additionalWslEnv.push_back (L' :' );
97+ }
98+ }
99+
70100 if (_environment)
71101 {
72102 // Order the environment variable names so that resolution order is consistent
103+ // NOTE(lhecker): I'm like 99% sure that this is unnecessary.
73104 std::set<std::wstring, til::env_key_sorter> keys{};
74105 for (const auto item : _environment)
75106 {
@@ -85,18 +116,39 @@ namespace winrt::Microsoft::Terminal::TerminalConnection::implementation
85116 const auto value = winrt::unbox_value<hstring>(_environment.Lookup (key));
86117
87118 environment.set_user_environment_var (key.c_str (), value.c_str ());
88- // For each environment variable added to the environment, also add it to WSLENV
89- wslEnv += key + L" :" ;
119+
120+ // WSLENV.4: Add custom user environment variables to WSLENV.
121+ if (wslEnvVars.emplace (key).second )
122+ {
123+ additionalWslEnv.append (key);
124+ additionalWslEnv.push_back (L' :' );
125+ }
90126 }
91127 CATCH_LOG ();
92128 }
93129 }
94130
95- // We want to prepend new environment variables to WSLENV - that way if a variable already
96- // exists in WSLENV but with a flag, the flag will be respected.
97- // (This behaviour was empirically observed)
98- wslEnv += environment.as_map ()[L" WSLENV" ];
99- environment.as_map ().insert_or_assign (L" WSLENV" , wslEnv);
131+ if (!additionalWslEnv.empty ())
132+ {
133+ // WSLENV.5: In the next step we'll prepend `additionalWslEnv` to `wslEnv`,
134+ // so make sure that we have a single colon in between them.
135+ const auto hasColon = additionalWslEnv.ends_with (L' :' );
136+ const auto needsColon = !wslEnv.starts_with (L' :' );
137+ if (hasColon != needsColon)
138+ {
139+ if (hasColon)
140+ {
141+ additionalWslEnv.pop_back ();
142+ }
143+ else
144+ {
145+ additionalWslEnv.push_back (L' :' );
146+ }
147+ }
148+
149+ // WSLENV.6: Prepend our additional environment variables to WSLENV.
150+ wslEnv.insert (0 , additionalWslEnv);
151+ }
100152 }
101153
102154 auto newEnvVars = environment.to_string ();
0 commit comments