| && self.get_resolve_in_parent_path() |
| && self.env_saw_path() |
| && self.get_program_kind() == ProgramKind::PathLookup |
| { |
| use crate::ffi::CStr; |
| // execvpe is a gnu extension... |
| #[cfg(all(target_os = "linux", target_env = "gnu"))] |
| unsafe fn exec_with_env( |
| program: &CStr, |
| args: &CStringArray, |
| envp: &CStringArray, |
| ) -> io::Error { |
| unsafe { libc::execvpe(program.as_ptr(), args.as_ptr(), envp.as_ptr()) }; |
| io::Error::last_os_error() |
| } |
|
| // ...so if we're not gnu then use our own implementation. |
| #[cfg(not(all(target_os = "linux", target_env = "gnu")))] |
| unsafe fn exec_with_env( |
| program: &CStr, |
| args: &CStringArray, |
| envp: &CStringArray, |
| ) -> io::Error { |
| unsafe { |
| let name = program.to_bytes(); |
| let mut buffer = |
| [const { mem::MaybeUninit::<u8>::uninit() }; libc::PATH_MAX as usize]; |
| let mut environ = *sys::env::environ(); |
| // Search the environment for PATH and, if found, |
| // search the paths for the executable by trying to execve each candidate. |
| while !(*environ).is_null() { |
| let kv = CStr::from_ptr(*environ); |
| if let Some(value) = kv.to_bytes().strip_prefix(b"PATH=") { |
| for path in value.split(|&b |
| if buffer.len() - 2 >= path.len().saturating_add(name.len()) { |
| let buf_ptr = buffer.as_mut_ptr().cast::<u8>(); |
| let mut offset = 0; |
| if !path.is_empty() { |
| buf_ptr.copy_from(path.as_ptr(), path.len()); |
| offset += path.len(); |
| if path.last() != Some(&b'/') { |
| *buf_ptr.add(path.len()) = b'/'; |
| offset += 1; |
| } |
| } |
| buf_ptr.add(offset).copy_from(name.as_ptr(), name.len()); |
| offset += name.len(); |
| *buf_ptr.add(offset) = 0; |
| libc::execve(buf_ptr.cast(), args.as_ptr(), envp.as_ptr()); |
| } |
| } |
| break; |
| } |
| environ = environ.add(1); |
| } |
| // If execve is successful then it'll never return, |
| // thus we only reach this point on failure.. |
| io::Error::from_raw_os_error(libc::ENOENT) |
| } |
| } |
| _reset = Some(Reset(*sys::env::environ())); |
| return Err(exec_with_env(self.get_program_cstr(), self.get_argv(), envp)); |
| } else if let Some(envp) = maybe_envp { |