|  | @@ -1,6 +1,12 @@
 | 
	
		
			
				|  |  |  // Start code adapted from https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/start.rs
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -use alloc::{borrow::ToOwned, boxed::Box, collections::BTreeMap, string::String, vec::Vec};
 | 
	
		
			
				|  |  | +use alloc::{
 | 
	
		
			
				|  |  | +    borrow::ToOwned,
 | 
	
		
			
				|  |  | +    boxed::Box,
 | 
	
		
			
				|  |  | +    collections::BTreeMap,
 | 
	
		
			
				|  |  | +    string::{String, ToString},
 | 
	
		
			
				|  |  | +    vec::Vec,
 | 
	
		
			
				|  |  | +};
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  use crate::{
 | 
	
		
			
				|  |  |      c_str::CStr,
 | 
	
	
		
			
				|  | @@ -12,8 +18,9 @@ use crate::{
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  use super::{
 | 
	
		
			
				|  |  | +    access::accessible,
 | 
	
		
			
				|  |  |      debug::_r_debug,
 | 
	
		
			
				|  |  | -    linker::{Linker, DSO},
 | 
	
		
			
				|  |  | +    linker::{Linker, DSO, PATH_SEP},
 | 
	
		
			
				|  |  |      tcb::Tcb,
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  use crate::header::sys_auxv::{AT_ENTRY, AT_PHDR};
 | 
	
	
		
			
				|  | @@ -116,9 +123,41 @@ unsafe fn adjust_stack(sp: &'static mut Stack) {
 | 
	
		
			
				|  |  |              break;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      sp.argc -= 1;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +fn resolve_path_name(
 | 
	
		
			
				|  |  | +    name_or_path: &str,
 | 
	
		
			
				|  |  | +    envs: &BTreeMap<String, String>,
 | 
	
		
			
				|  |  | +) -> Option<(String, String)> {
 | 
	
		
			
				|  |  | +    if accessible(name_or_path, unistd::F_OK) == 0 {
 | 
	
		
			
				|  |  | +        return Some((
 | 
	
		
			
				|  |  | +            name_or_path.to_string(),
 | 
	
		
			
				|  |  | +            name_or_path
 | 
	
		
			
				|  |  | +                .split("/")
 | 
	
		
			
				|  |  | +                .collect::<Vec<&str>>()
 | 
	
		
			
				|  |  | +                .last()
 | 
	
		
			
				|  |  | +                .unwrap()
 | 
	
		
			
				|  |  | +                .to_string(),
 | 
	
		
			
				|  |  | +        ));
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    if name_or_path.split("/").collect::<Vec<&str>>().len() != 1 {
 | 
	
		
			
				|  |  | +        return None;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let env_path = envs.get("PATH")?;
 | 
	
		
			
				|  |  | +    for part in env_path.split(PATH_SEP) {
 | 
	
		
			
				|  |  | +        let path = if part.is_empty() {
 | 
	
		
			
				|  |  | +            format!("./{}", name_or_path)
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +            format!("{}/{}", part, name_or_path)
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        if accessible(&path, unistd::F_OK) == 0 {
 | 
	
		
			
				|  |  | +            return Some((path.to_string(), name_or_path.to_string()));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    None
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  #[no_mangle]
 | 
	
		
			
				|  |  |  pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) -> usize {
 | 
	
		
			
				|  |  |      // First thing we initialize the mspace
 | 
	
	
		
			
				|  | @@ -149,7 +188,7 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
 | 
	
		
			
				|  |  |          None => "/lib".to_owned(),
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    let path = if is_manual {
 | 
	
		
			
				|  |  | +    let name_or_path = if is_manual {
 | 
	
		
			
				|  |  |          // ld.so is run directly by user and not via execve() or similar systemcall
 | 
	
		
			
				|  |  |          println!("argv: {:#?}", argv);
 | 
	
		
			
				|  |  |          println!("envs: {:#?}", envs);
 | 
	
	
		
			
				|  | @@ -161,13 +200,23 @@ pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack, ld_entry: usize) ->
 | 
	
		
			
				|  |  |              loop {}
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          unsafe { adjust_stack(sp) };
 | 
	
		
			
				|  |  | -        &argv[1]
 | 
	
		
			
				|  |  | +        argv[1].to_string()
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  | -        &argv[0]
 | 
	
		
			
				|  |  | +        argv[0].to_string()
 | 
	
		
			
				|  |  |      };
 | 
	
		
			
				|  |  | -    // if we are not running in manual mode, then the main program is already
 | 
	
		
			
				|  |  | -    // loaded by the linux kernel and we want to use it. on redox, we treat it
 | 
	
		
			
				|  |  | -    // the same.
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    let (path, name) = match resolve_path_name(&name_or_path, &envs) {
 | 
	
		
			
				|  |  | +        Some((p, n)) => (p, n),
 | 
	
		
			
				|  |  | +        None => {
 | 
	
		
			
				|  |  | +            eprintln!("ld.so: failed to locate '{}'", name_or_path);
 | 
	
		
			
				|  |  | +            unistd::_exit(1);
 | 
	
		
			
				|  |  | +            loop {}
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // if we are not running in manual mode, then the main
 | 
	
		
			
				|  |  | +    // program is already loaded by the kernel and we want
 | 
	
		
			
				|  |  | +    // to use it. on redox, we treat it the same.
 | 
	
		
			
				|  |  |      let program = {
 | 
	
		
			
				|  |  |          let mut pr = None;
 | 
	
		
			
				|  |  |          if !is_manual && cfg!(not(target_os = "redox")) {
 |