@@ -65,8 +65,7 @@ func startPty(cmd *exec.Cmd) (PTY, error) {
65
65
false ,
66
66
// https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags#create_unicode_environment
67
67
windows .CREATE_UNICODE_ENVIRONMENT | windows .EXTENDED_STARTUPINFO_PRESENT ,
68
- // Environment variables can come later!
69
- createEnvBlock ([]string {"SYSTEMROOT=" + os .Getenv ("SYSTEMROOT" )}),
68
+ createEnvBlock (addCriticalEnv (dedupEnvCase (true , cmd .Env ))),
70
69
dirPtr ,
71
70
& startupInfo .StartupInfo ,
72
71
& processInfo ,
@@ -103,3 +102,46 @@ func createEnvBlock(envv []string) *uint16 {
103
102
104
103
return & utf16 .Encode ([]rune (string (b )))[0 ]
105
104
}
105
+
106
+ // dedupEnvCase is dedupEnv with a case option for testing.
107
+ // If caseInsensitive is true, the case of keys is ignored.
108
+ func dedupEnvCase (caseInsensitive bool , env []string ) []string {
109
+ out := make ([]string , 0 , len (env ))
110
+ saw := make (map [string ]int , len (env )) // key => index into out
111
+ for _ , kv := range env {
112
+ eq := strings .Index (kv , "=" )
113
+ if eq < 0 {
114
+ out = append (out , kv )
115
+ continue
116
+ }
117
+ k := kv [:eq ]
118
+ if caseInsensitive {
119
+ k = strings .ToLower (k )
120
+ }
121
+ if dupIdx , isDup := saw [k ]; isDup {
122
+ out [dupIdx ] = kv
123
+ continue
124
+ }
125
+ saw [k ] = len (out )
126
+ out = append (out , kv )
127
+ }
128
+ return out
129
+ }
130
+
131
+ // addCriticalEnv adds any critical environment variables that are required
132
+ // (or at least almost always required) on the operating system.
133
+ // Currently this is only used for Windows.
134
+ func addCriticalEnv (env []string ) []string {
135
+ for _ , kv := range env {
136
+ eq := strings .Index (kv , "=" )
137
+ if eq < 0 {
138
+ continue
139
+ }
140
+ k := kv [:eq ]
141
+ if strings .EqualFold (k , "SYSTEMROOT" ) {
142
+ // We already have it.
143
+ return env
144
+ }
145
+ }
146
+ return append (env , "SYSTEMROOT=" + os .Getenv ("SYSTEMROOT" ))
147
+ }
0 commit comments