Execute a new process # Arguments `bin` - A slice containing ELF binary data `flags` - Permission flags `stdin` - The new process' STDIN communication handle `stdout` - The new process' STDOUT communication handle. `vfs` - Virtual File System specification `args` - Command-line arguments `env` - Environment string Returns the thread ID if successful, or a `SyscallError`
(
bin: &[u8],
flags: u8,
mut stdin: CommHandle,
mut stdout: CommHandle,
vfs: VFS,
args: Vec<&str>,
env: &str,
)
| 512 | /// |
| 513 | /// Returns the thread ID if successful, or a `SyscallError` |
| 514 | pub fn exec( |
| 515 | bin: &[u8], |
| 516 | flags: u8, |
| 517 | mut stdin: CommHandle, |
| 518 | mut stdout: CommHandle, |
| 519 | vfs: VFS, |
| 520 | args: Vec<&str>, |
| 521 | env: &str, |
| 522 | ) -> Result<u64, SyscallError> { |
| 523 | |
| 524 | let mut params = String::new(); |
| 525 | let param_str = if (args.len() == 0) & (env.len() == 0) { |
| 526 | vfs.as_str() |
| 527 | } else { |
| 528 | params.push_str(vfs.as_str()); |
| 529 | if args.len() != 0 { |
| 530 | params.push('A'); // Start of arguments |
| 531 | |
| 532 | let mut arg_it = args.iter().peekable(); |
| 533 | while let Some(arg) = arg_it.next() { |
| 534 | params.push_str(arg); |
| 535 | if arg_it.peek().is_some() { |
| 536 | params.push(0x03 as char); // Argument separator |
| 537 | } |
| 538 | } |
| 539 | params.push('\0'); // End of arguments |
| 540 | } |
| 541 | if env.len() != 0 { |
| 542 | if env.contains('\0') { |
| 543 | // String must not contain null characters |
| 544 | // because it will be null terminated. |
| 545 | return Err(SYSCALL_ERROR_PARAM); |
| 546 | } |
| 547 | params.push('E'); |
| 548 | params.push_str(env); |
| 549 | params.push('\0'); // End of environment |
| 550 | } |
| 551 | ¶ms |
| 552 | }; |
| 553 | |
| 554 | let error: u64; |
| 555 | let tid: u64; |
| 556 | unsafe { |
| 557 | asm!("syscall", |
| 558 | // RAX contains | bin length (32) | param length (16) | flags (8) | syscall (8) |
| 559 | in("rax") SYSCALL_EXEC | ((flags as u64) << 8) | ((param_str.len() as u64) << 16) | ((bin.len() as u64) << 32), |
| 560 | // RDI contains pointer to ELF binary data |
| 561 | in("rdi") bin.as_ptr() as usize, |
| 562 | // RSI contains STDIN & STDOUT handles |
| 563 | in("rsi") ((stdin.take() as u64) << 32) | (stdout.take() as u64), |
| 564 | // RDX will contain a pointer to a parameter string |
| 565 | in("rdx") param_str.as_ptr() as usize, |
| 566 | lateout("rax") error, |
| 567 | lateout("rdi") tid, |
| 568 | out("rcx") _, |
| 569 | out("r11") _); |
| 570 | } |
| 571 | if error == 0 { |