Jeremy Soller 6 роки тому
батько
коміт
a29aa9f599
2 змінених файлів з 48 додано та 3 видалено
  1. 38 3
      src/header/unistd/mod.rs
  2. 10 0
      src/macros.rs

+ 38 - 3
src/header/unistd/mod.rs

@@ -3,7 +3,9 @@
 use core::{ptr, slice};
 
 use c_str::CStr;
+use header::errno;
 use header::limits;
+use header::stdlib::getenv;
 use header::time::timespec;
 use platform;
 use platform::types::*;
@@ -150,9 +152,42 @@ pub unsafe extern "C" fn execve(
     Sys::execve(path, argv, envp)
 }
 
-// #[no_mangle]
-pub extern "C" fn execvp(file: *const c_char, argv: *const *mut c_char) -> c_int {
-    unimplemented!();
+#[cfg(target_os = "linux")]
+const PATH_SEPARATOR: u8 = b':';
+
+#[cfg(target_os = "redox")]
+const PATH_SEPARATOR: u8 = b';';
+
+#[no_mangle]
+pub unsafe extern "C" fn execvp(file: *const c_char, argv: *const *mut c_char) -> c_int {
+    let file = CStr::from_ptr(file);
+
+    if file.to_bytes().contains(&b'/') || (cfg!(target_os = "redox") && file.to_bytes().contains(&b':')) {
+        execv(file.as_ptr(), argv)
+    } else {
+        let mut error = errno::ENOENT;
+
+        let path_env = getenv(c_str!("PATH\0").as_ptr());
+        if ! path_env.is_null() {
+            let path_env = CStr::from_ptr(path_env);
+            for mut path in path_env.to_bytes().split(|&b| b == PATH_SEPARATOR) {
+                let mut program = path.to_vec();
+                program.extend_from_slice(file.to_bytes());
+                program.push(b'0');
+
+                let program_c = CStr::from_bytes_with_nul(&program).unwrap();
+                execv(program_c.as_ptr(), argv);
+
+                match platform::errno {
+                    errno::ENOENT => (),
+                    other => error = other,
+                }
+            }
+        }
+
+        platform::errno = error;
+        -1
+    }
 }
 
 #[no_mangle]

+ 10 - 0
src/macros.rs

@@ -1,3 +1,13 @@
+#[macro_export]
+macro_rules! c_str {
+    ($lit:expr) => {
+        unsafe {
+            $crate::c_str::CStr::from_ptr(concat!($lit, "\0").as_ptr()
+                as *const $crate::platform::types::c_char)
+        }
+    }
+}
+
 /// Print to stdout
 #[macro_export]
 macro_rules! print {