Skip to content
Snippets Groups Projects
Commit 165f099c authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Update Redox platform to pal

parent 729709a8
No related branches found
No related tags found
No related merge requests found
use core::{mem, ptr}; use core::{mem, ptr};
use core::fmt::Write; use core::fmt::Write;
use FileWriter; use {errno, FileWriter, Pal};
use Pal;
use errno;
use types::*; use types::*;
mod signal; mod signal;
...@@ -81,8 +79,8 @@ impl Pal for Sys { ...@@ -81,8 +79,8 @@ impl Pal for Sys {
e(unsafe { syscall!(DUP3, fildes, fildes2, 0) }) as c_int e(unsafe { syscall!(DUP3, fildes, fildes2, 0) }) as c_int
} }
fn execve(path: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int { unsafe fn execve(path: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
e(unsafe { syscall!(EXECVE, path, argv, envp) }) as c_int e(syscall!(EXECVE, path, argv, envp)) as c_int
} }
fn exit(status: c_int) -> ! { fn exit(status: c_int) -> ! {
......
...@@ -45,7 +45,7 @@ pub trait Pal { ...@@ -45,7 +45,7 @@ pub trait Pal {
Self::no_pal("dup2") Self::no_pal("dup2")
} }
fn execve(path: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int { unsafe fn execve(path: *const c_char, argv: *const *mut c_char, envp: *const *mut c_char) -> c_int {
Self::no_pal("execve") Self::no_pal("execve")
} }
......
This diff is collapsed.
impl PalSignal for Sys {
fn kill(pid: pid_t, sig: c_int) -> c_int {
e(syscall::kill(pid as usize, sig as usize)) as c_int
}
fn killpg(pgrp: pid_t, sig: c_int) -> c_int {
e(syscall::kill(-(pgrp as isize) as usize, sig as usize)) as c_int
}
fn raise(sig: c_int) -> c_int {
kill(getpid(), sig)
}
unsafe fn sigaction(sig: c_int, act: *const sigaction, oact: *mut sigaction) -> c_int {
if !oact.is_null() {
// Assumes the last sigaction() call was made by relibc and not a different one
if SIG_HANDLER.is_some() {
(*oact).sa_handler = SIG_HANDLER;
}
}
let act = if act.is_null() {
None
} else {
SIG_HANDLER = (*act).sa_handler;
let m = (*act).sa_mask;
Some(syscall::SigAction {
sa_handler: sig_handler,
sa_mask: [0, m as u64],
sa_flags: (*act).sa_flags as usize,
})
};
let mut old = syscall::SigAction::default();
let ret = e(syscall::sigaction(
sig as usize,
act.as_ref(),
if oact.is_null() { None } else { Some(&mut old) },
)) as c_int;
if !oact.is_null() {
let m = old.sa_mask;
(*oact).sa_mask = m[1] as c_ulong;
(*oact).sa_flags = old.sa_flags as c_ulong;
}
ret
}
//fn sigprocmask(how: c_int, set: *const sigset_t, oset: *mut sigset_t) -> c_int;
}
macro_rules! bind_or_connect {
(bind $path:expr) => {
concat!("/", $path)
};
(connect $path:expr) => {
$path
};
($mode:ident $socket:expr, $address:expr, $address_len:expr) => {{
if (*$address).sa_family as c_int != AF_INET {
errno = syscall::EAFNOSUPPORT;
return -1;
}
if ($address_len as usize) < mem::size_of::<sockaddr>() {
errno = syscall::EINVAL;
return -1;
}
let data = &*($address as *const sockaddr_in);
let addr = &data.sin_addr.s_addr;
let port = in_port_t::from_be(data.sin_port); // This is transmuted from bytes in BigEndian order
let path = format!(bind_or_connect!($mode "{}.{}.{}.{}:{}"), addr[0], addr[1], addr[2], addr[3], port);
// Duplicate the socket, and then duplicate the copy back to the original fd
let fd = e(syscall::dup($socket as usize, path.as_bytes()));
if (fd as c_int) < 0 {
return -1;
}
let result = syscall::dup2(fd, $socket as usize, &[]);
let _ = syscall::close(fd);
if (e(result) as c_int) < 0 {
return -1;
}
0
}}
}
unsafe fn inner_get_name(
local: bool,
socket: c_int,
address: *mut sockaddr,
address_len: *mut socklen_t,
) -> Result<usize> {
// 32 should probably be large enough.
// Format: tcp:remote/local
// and since we only yet support IPv4 (I think)...
let mut buf = [0; 32];
let len = syscall::fpath(socket as usize, &mut buf)?;
let buf = &buf[..len];
assert!(&buf[..4] == b"tcp:" || &buf[..4] == b"udp:");
let buf = &buf[4..];
let mut parts = buf.split(|c| *c == b'/');
if local {
// Skip the remote part
parts.next();
}
let part = parts.next().expect("Invalid reply from netstack");
let data = slice::from_raw_parts_mut(
&mut (*address).data as *mut _ as *mut u8,
(*address).data.len(),
);
let len = data.len().min(part.len());
data[..len].copy_from_slice(&part[..len]);
*address_len = len as socklen_t;
Ok(0)
}
impl PalSocket for Sys {
unsafe fn accept(socket: c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> c_int {
let stream = e(syscall::dup(socket as usize, b"listen")) as c_int;
if stream < 0 {
return -1;
}
if address != ptr::null_mut()
&& address_len != ptr::null_mut()
&& getpeername(stream, address, address_len) < 0
{
return -1;
}
stream
}
unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
bind_or_connect!(bind socket, address, address_len)
}
unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int {
bind_or_connect!(connect socket, address, address_len)
}
unsafe fn getpeername(
socket: c_int,
address: *mut sockaddr,
address_len: *mut socklen_t,
) -> c_int {
e(inner_get_name(false, socket, address, address_len)) as c_int
}
unsafe fn getsockname(
socket: c_int,
address: *mut sockaddr,
address_len: *mut socklen_t,
) -> c_int {
e(inner_get_name(true, socket, address, address_len)) as c_int
}
unsafe fn recvfrom(
socket: c_int,
buf: *mut c_void,
len: size_t,
flags: c_int,
address: *mut sockaddr,
address_len: *mut socklen_t,
) -> ssize_t {
if flags != 0 {
errno = syscall::EOPNOTSUPP;
return -1;
}
if address != ptr::null_mut()
&& address_len != ptr::null_mut()
&& getpeername(socket, address, address_len) < 0
{
return -1;
}
read(socket, slice::from_raw_parts_mut(buf as *mut u8, len))
}
unsafe fn sendto(
socket: c_int,
buf: *const c_void,
len: size_t,
flags: c_int,
dest_addr: *const sockaddr,
dest_len: socklen_t,
) -> ssize_t {
if dest_addr != ptr::null() || dest_len != 0 {
errno = syscall::EISCONN;
return -1;
}
if flags != 0 {
errno = syscall::EOPNOTSUPP;
return -1;
}
write(socket, slice::from_raw_parts(buf as *const u8, len))
}
unsafe fn socket(domain: c_int, mut kind: c_int, protocol: c_int) -> c_int {
if domain != AF_INET {
errno = syscall::EAFNOSUPPORT;
return -1;
}
if protocol != 0 {
errno = syscall::EPROTONOSUPPORT;
return -1;
}
let mut flags = O_RDWR;
if kind & SOCK_NONBLOCK == SOCK_NONBLOCK {
kind &= !SOCK_NONBLOCK;
flags |= O_NONBLOCK;
}
if kind & SOCK_CLOEXEC == SOCK_CLOEXEC {
kind &= !SOCK_CLOEXEC;
flags |= O_CLOEXEC;
}
// The tcp: and udp: schemes allow using no path,
// and later specifying one using `dup`.
match kind {
SOCK_STREAM => e(syscall::open("tcp:", flags)) as c_int,
SOCK_DGRAM => e(syscall::open("udp:", flags)) as c_int,
_ => {
errno = syscall::EPROTOTYPE;
-1
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment