|
8 | 8 | // option. This file may not be copied, modified, or distributed |
9 | 9 | // except according to those terms. |
10 | 10 |
|
11 | | -use env; |
12 | | -use ffi::CString; |
13 | 11 | use io::{self, Error, ErrorKind}; |
14 | 12 | use libc::{self, c_int, gid_t, pid_t, uid_t}; |
15 | 13 | use ptr; |
@@ -41,15 +39,13 @@ impl Command { |
41 | 39 | return Ok((ret, ours)) |
42 | 40 | } |
43 | 41 |
|
44 | | - let possible_paths = self.compute_possible_paths(envp.as_ref()); |
45 | | - |
46 | 42 | let (input, output) = sys::pipe::anon_pipe()?; |
47 | 43 |
|
48 | 44 | let pid = unsafe { |
49 | 45 | match cvt(libc::fork())? { |
50 | 46 | 0 => { |
51 | 47 | drop(input); |
52 | | - let err = self.do_exec(theirs, envp.as_ref(), possible_paths); |
| 48 | + let err = self.do_exec(theirs, envp.as_ref()); |
53 | 49 | let errno = err.raw_os_error().unwrap_or(libc::EINVAL) as u32; |
54 | 50 | let bytes = [ |
55 | 51 | (errno >> 24) as u8, |
@@ -117,48 +113,12 @@ impl Command { |
117 | 113 | "nul byte found in provided data") |
118 | 114 | } |
119 | 115 |
|
120 | | - let possible_paths = self.compute_possible_paths(envp.as_ref()); |
121 | 116 | match self.setup_io(default, true) { |
122 | | - Ok((_, theirs)) => unsafe { self.do_exec(theirs, envp.as_ref(), possible_paths) }, |
| 117 | + Ok((_, theirs)) => unsafe { self.do_exec(theirs, envp.as_ref()) }, |
123 | 118 | Err(e) => e, |
124 | 119 | } |
125 | 120 | } |
126 | 121 |
|
127 | | - fn compute_possible_paths(&self, maybe_envp: Option<&CStringArray>) -> Option<Vec<CString>> { |
128 | | - let program = self.get_program().as_bytes(); |
129 | | - if program.contains(&b'/') { |
130 | | - return None; |
131 | | - } |
132 | | - // Outside the match so we can borrow it for the lifetime of the function. |
133 | | - let parent_path = env::var("PATH").ok(); |
134 | | - let paths = match maybe_envp { |
135 | | - Some(envp) => { |
136 | | - match envp.get_items().iter().find(|var| var.as_bytes().starts_with(b"PATH=")) { |
137 | | - Some(p) => &p.as_bytes()[5..], |
138 | | - None => return None, |
139 | | - } |
140 | | - }, |
141 | | - // maybe_envp is None if the process isn't changing the parent's env at all. |
142 | | - None => { |
143 | | - match parent_path.as_ref() { |
144 | | - Some(p) => p.as_bytes(), |
145 | | - None => return None, |
146 | | - } |
147 | | - }, |
148 | | - }; |
149 | | - |
150 | | - let mut possible_paths = vec![]; |
151 | | - for path in paths.split(|p| *p == b':') { |
152 | | - let mut binary_path = Vec::with_capacity(program.len() + path.len() + 1); |
153 | | - binary_path.extend_from_slice(path); |
154 | | - binary_path.push(b'/'); |
155 | | - binary_path.extend_from_slice(program); |
156 | | - let c_binary_path = CString::new(binary_path).unwrap(); |
157 | | - possible_paths.push(c_binary_path); |
158 | | - } |
159 | | - return Some(possible_paths); |
160 | | - } |
161 | | - |
162 | 122 | // And at this point we've reached a special time in the life of the |
163 | 123 | // child. The child must now be considered hamstrung and unable to |
164 | 124 | // do anything other than syscalls really. Consider the following |
@@ -192,8 +152,7 @@ impl Command { |
192 | 152 | unsafe fn do_exec( |
193 | 153 | &mut self, |
194 | 154 | stdio: ChildPipes, |
195 | | - maybe_envp: Option<&CStringArray>, |
196 | | - maybe_possible_paths: Option<Vec<CString>>, |
| 155 | + maybe_envp: Option<&CStringArray> |
197 | 156 | ) -> io::Error { |
198 | 157 | use sys::{self, cvt_r}; |
199 | 158 |
|
@@ -234,6 +193,9 @@ impl Command { |
234 | 193 | if let Some(ref cwd) = *self.get_cwd() { |
235 | 194 | t!(cvt(libc::chdir(cwd.as_ptr()))); |
236 | 195 | } |
| 196 | + if let Some(envp) = maybe_envp { |
| 197 | + *sys::os::environ() = envp.as_ptr(); |
| 198 | + } |
237 | 199 |
|
238 | 200 | // emscripten has no signal support. |
239 | 201 | #[cfg(not(any(target_os = "emscripten")))] |
@@ -269,53 +231,8 @@ impl Command { |
269 | 231 | t!(callback()); |
270 | 232 | } |
271 | 233 |
|
272 | | - // If the program isn't an absolute path, and our environment contains a PATH var, then we |
273 | | - // implement the PATH traversal ourselves so that it honors the child's PATH instead of the |
274 | | - // parent's. This mirrors the logic that exists in glibc's execvpe, except using the |
275 | | - // child's env to fetch PATH. |
276 | | - match maybe_possible_paths { |
277 | | - Some(possible_paths) => { |
278 | | - let mut pending_error = None; |
279 | | - for path in possible_paths { |
280 | | - libc::execve( |
281 | | - path.as_ptr(), |
282 | | - self.get_argv().as_ptr(), |
283 | | - maybe_envp.map(|envp| envp.as_ptr()).unwrap_or_else(|| *sys::os::environ()) |
284 | | - ); |
285 | | - let err = io::Error::last_os_error(); |
286 | | - match err.kind() { |
287 | | - io::ErrorKind::PermissionDenied => { |
288 | | - // If we saw a PermissionDenied, and none of the other entries in |
289 | | - // $PATH are successful, then we'll return the first EACCESS we see. |
290 | | - if pending_error.is_none() { |
291 | | - pending_error = Some(err); |
292 | | - } |
293 | | - }, |
294 | | - // Errors which indicate we failed to find a file are ignored and we try |
295 | | - // the next entry in the path. |
296 | | - io::ErrorKind::NotFound | io::ErrorKind::TimedOut => { |
297 | | - continue |
298 | | - }, |
299 | | - // Any other error means we found a file and couldn't execute it. |
300 | | - _ => { |
301 | | - return err; |
302 | | - } |
303 | | - } |
304 | | - } |
305 | | - if let Some(err) = pending_error { |
306 | | - return err; |
307 | | - } |
308 | | - return io::Error::from_raw_os_error(libc::ENOENT); |
309 | | - }, |
310 | | - _ => { |
311 | | - libc::execve( |
312 | | - self.get_argv()[0], |
313 | | - self.get_argv().as_ptr(), |
314 | | - maybe_envp.map(|envp| envp.as_ptr()).unwrap_or_else(|| *sys::os::environ()) |
315 | | - ); |
316 | | - return io::Error::last_os_error() |
317 | | - } |
318 | | - } |
| 234 | + libc::execvp(self.get_argv()[0], self.get_argv().as_ptr()); |
| 235 | + io::Error::last_os_error() |
319 | 236 | } |
320 | 237 |
|
321 | 238 | #[cfg(not(any(target_os = "macos", target_os = "freebsd", |
|
0 commit comments