diff --git a/Cargo.lock b/Cargo.lock index a719fd585df9510c98ed0778a89903fd16abf35f..bffba2450af24862b8be8d44fea95ecf0e03d539 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,6 +304,7 @@ dependencies = [ "stdio 0.1.0", "stdlib 0.1.0", "string 0.1.0", + "strings 0.1.0", "sys_mman 0.1.0", "sys_resource 0.1.0", "sys_socket 0.1.0", @@ -446,6 +447,14 @@ dependencies = [ "platform 0.1.0", ] +[[package]] +name = "strings" +version = "0.1.0" +dependencies = [ + "cbindgen 0.5.2", + "platform 0.1.0", +] + [[package]] name = "strsim" version = "0.7.0" diff --git a/Cargo.toml b/Cargo.toml index 9514720270cdd499596efb0a759e22f6a1d1bed7..db0493f13ff50273f8cfd7871c7671476fd0d8d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ signal = { path = "src/signal" } stdio = { path = "src/stdio" } stdlib = { path = "src/stdlib" } string = { path = "src/string" } +strings = { path = "src/strings" } sys_mman = { path = "src/sys_mman" } sys_resource = { path = "src/sys_resource" } sys_socket = { path = "src/sys_socket" } diff --git a/include/sys/param.h b/include/sys/param.h new file mode 100644 index 0000000000000000000000000000000000000000..68ff8c172c2a9e174b9e94c8337b5ede112fdbe1 --- /dev/null +++ b/include/sys/param.h @@ -0,0 +1,34 @@ +#ifndef _SYS_PARAM_H +#define _SYS_PARAM_H + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) + +#define __bitop(array, index, op) ((array)[(index) / 8] op (1 << (index) % 8)) +#define setbit(array, index) __bitop(array, index, |=) +#define clrbit(array, index) __bitop(array, index, &= ~) +#define isset(array, index) __bitop(array, index, &) +#define isclr(array, index) !isset(array, index) + +#define howmany(bits, size) (((bits) + (size) - 1) / (size)) +#define roundup(bits, size) (howmany(bits, size) * (size)) +#define powerof2(n) !(((n) - 1) & (n)) + +// Shamelessly copied from musl. +// Tweak as needed. +#define MAXSYMLINKS 20 +#define MAXHOSTNAMELEN 64 +#define MAXNAMLEN 255 +#define MAXPATHLEN 4096 +#define NBBY 8 +#define NGROUPS 32 +#define CANBSIZ 255 +#define NOFILE 256 +#define NCARGS 131072 +#define DEV_BSIZE 512 +#define NOGROUP (-1) + +#include <sys/resource.h> +#include <limits.h> + +#endif diff --git a/src/ctype/src/lib.rs b/src/ctype/src/lib.rs index bcbc443f538c7303c285253f95e6731254e57c9a..a9f602043f72cca1304b1deb900a143339eeef43 100644 --- a/src/ctype/src/lib.rs +++ b/src/ctype/src/lib.rs @@ -18,7 +18,7 @@ pub extern "C" fn isalpha(c: c_int) -> c_int { #[no_mangle] pub extern "C" fn isascii(c: c_int) -> c_int { - (!(c & !0x7f)) as c_int + ((c & !0x7f) == 0) as c_int } #[no_mangle] diff --git a/src/lib.rs b/src/lib.rs index a03b7a4564e45708f6b0f13267a8a95c6063e265..e1da46a8d62f6094b612ebf32bfb384cab2ad100 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,6 +20,7 @@ pub extern crate signal; pub extern crate stdio; pub extern crate stdlib; pub extern crate string; +pub extern crate strings; pub extern crate sys_mman; pub extern crate sys_resource; pub extern crate sys_socket; diff --git a/src/platform/src/lib.rs b/src/platform/src/lib.rs index 5d95b235f1207cc4544b0611246fc98027909e92..e9b3bb8b834b895f5e81debab7b412f76ff52675 100644 --- a/src/platform/src/lib.rs +++ b/src/platform/src/lib.rs @@ -4,6 +4,7 @@ #![feature(allocator_api)] //TODO #![feature(thread_local)] +#[cfg_attr(target_os = "redox", macro_use)] extern crate alloc; #[cfg(all(not(feature = "no_std"), target_os = "linux"))] @@ -43,6 +44,22 @@ use types::*; #[global_allocator] static ALLOCATOR: Allocator = Allocator; +pub const AF_INET: c_int = 2; +pub const SOCK_STREAM: c_int = 1; +pub const SOCK_DGRAM: c_int = 2; +pub const SOCK_NONBLOCK: c_int = 0o4000; +pub const SOCK_CLOEXEC: c_int = 0o2000000; + +pub type in_addr_t = [u8; 4]; +pub type in_port_t = u16; +pub type sa_family_t = u16; +pub type socklen_t = u32; + +pub struct sockaddr { + pub sa_family: sa_family_t, + pub data: [c_char; 14] +} + //TODO #[thread_local] #[allow(non_upper_case_globals)] #[no_mangle] diff --git a/src/platform/src/linux/mod.rs b/src/platform/src/linux/mod.rs index 9a8e783e6f6f665c7d6887a5e19f0979ad26dcbd..89bbb2150824cc1c3c13a9ae86cb9f8fc9d805ed 100644 --- a/src/platform/src/linux/mod.rs +++ b/src/platform/src/linux/mod.rs @@ -1,6 +1,6 @@ use core::ptr; -use errno; +use ::*; use types::*; const AT_FDCWD: c_int = -100; @@ -19,6 +19,10 @@ pub fn e(sys: usize) -> usize { } } +pub unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int { + e(syscall!(BIND, socket, address, address_len)) as c_int +} + pub fn brk(addr: *mut c_void) -> *mut c_void { unsafe { syscall!(BRK, addr) as *mut c_void } } @@ -39,6 +43,10 @@ pub fn close(fildes: c_int) -> c_int { e(unsafe { syscall!(CLOSE, fildes) }) as c_int } +pub unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int { + e(syscall!(CONNECT, socket, address, address_len)) as c_int +} + pub fn dup(fildes: c_int) -> c_int { e(unsafe { syscall!(DUP, fildes) }) as c_int } @@ -171,6 +179,11 @@ pub fn read(fildes: c_int, buf: &mut [u8]) -> ssize_t { e(unsafe { syscall!(READ, fildes, buf.as_mut_ptr(), buf.len()) }) as ssize_t } +pub 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 { + e(syscall!(RECVFROM, socket, buf, len, flags, address, address_len)) as ssize_t +} + pub fn rename(old: *const c_char, new: *const c_char) -> c_int { e(unsafe { syscall!(RENAMEAT, AT_FDCWD, old, AT_FDCWD, new) }) as c_int } @@ -179,6 +192,11 @@ pub fn rmdir(path: *const c_char) -> c_int { e(unsafe { syscall!(UNLINKAT, AT_FDCWD, path, AT_REMOVEDIR) }) as c_int } +pub 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 { + e(syscall!(SENDTO, socket, buf, len, flags, dest_addr, dest_len)) as ssize_t +} + pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int { e(unsafe { syscall!(SETPGID, pid, pgid) }) as c_int } @@ -195,6 +213,10 @@ pub fn stat(file: *const c_char, buf: *mut stat) -> c_int { e(unsafe { syscall!(NEWFSTATAT, AT_FDCWD, file, buf, 0) }) as c_int } +pub fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int { + e(unsafe { syscall!(SOCKET, domain, kind, protocol) }) as c_int +} + pub fn uname(utsname: usize) -> c_int { e(unsafe { syscall!(UNAME, utsname, 0) }) as c_int } diff --git a/src/platform/src/redox/mod.rs b/src/platform/src/redox/mod.rs index a6db080e005eb684edea23c79bd21194600604a0..517105db853cf527f9200a06890ba59056d72395 100644 --- a/src/platform/src/redox/mod.rs +++ b/src/platform/src/redox/mod.rs @@ -1,3 +1,4 @@ +use alloc; use core::mem; use core::ptr; use core::slice; @@ -6,10 +7,16 @@ use syscall::data::Stat as redox_stat; use syscall::data::TimeSpec as redox_timespec; use syscall::flag::*; -use c_str; -use errno; +use ::*; use types::*; +#[repr(C)] +struct SockData { + port: in_port_t, + addr: in_addr_t, + _pad: [c_char; 8] +} + pub fn e(sys: Result<usize, syscall::Error>) -> usize { match sys { Ok(ok) => ok, @@ -22,6 +29,45 @@ pub fn e(sys: Result<usize, syscall::Error>) -> usize { } } +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: &SockData = mem::transmute(&(*$address).data); + let addr = &data.addr; + let port = in_port_t::from_be(data.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 + }} +} + +pub unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int { + bind_or_connect!(bind socket, address, address_len) +} + pub fn brk(addr: *mut c_void) -> *mut c_void { unsafe { syscall::brk(addr as usize).unwrap_or(0) as *mut c_void } } @@ -59,6 +105,10 @@ pub fn close(fd: c_int) -> c_int { e(syscall::close(fd as usize)) as c_int } +pub unsafe fn connect(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> c_int { + bind_or_connect!(connect socket, address, address_len) +} + pub fn dup(fd: c_int) -> c_int { e(syscall::dup(fd as usize, &[])) as c_int } @@ -331,6 +381,24 @@ pub fn read(fd: c_int, buf: &mut [u8]) -> ssize_t { e(syscall::read(fd as usize, buf)) as ssize_t } +pub 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; + } + let data = slice::from_raw_parts_mut( + &mut (*address).data as *mut _ as *mut u8, + (*address).data.len() + ); + let pathlen = e(syscall::fpath(socket as usize, data)); + if pathlen < 0 { + return -1; + } + *address_len = pathlen as socklen_t; + read(socket, slice::from_raw_parts_mut(buf as *mut u8, len)) +} + pub fn rename(oldpath: *const c_char, newpath: *const c_char) -> c_int { let (oldpath, newpath) = unsafe { (c_str(oldpath), c_str(newpath)) }; match syscall::open(oldpath, O_WRONLY) { @@ -348,6 +416,16 @@ pub fn rmdir(path: *const c_char) -> c_int { e(syscall::rmdir(path)) as c_int } +pub 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 { + // TODO: Use dest_addr and dest_len + if flags != 0 { + errno = syscall::EOPNOTSUPP; + return -1; + } + write(socket, slice::from_raw_parts(buf as *const u8, len)) +} + pub fn setpgid(pid: pid_t, pgid: pid_t) -> c_int { e(syscall::setpgid(pid as usize, pgid as usize)) as c_int } @@ -372,6 +450,38 @@ pub fn stat(path: *const c_char, buf: *mut stat) -> c_int { } } +pub 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 + } + } +} + pub fn unlink(path: *const c_char) -> c_int { let path = unsafe { c_str(path) }; e(syscall::unlink(path)) as c_int diff --git a/src/stdio/src/printf.rs b/src/stdio/src/printf.rs index b7a7bbfc48752a1c8213690144e469769f9697f6..174c603f843e9692ad11ae098b0bd50651ca6112 100644 --- a/src/stdio/src/printf.rs +++ b/src/stdio/src/printf.rs @@ -55,13 +55,11 @@ pub unsafe fn printf<W: Write>(mut w: W, format: *const c_char, mut ap: VaList) w.write_fmt(format_args!("0x{:x}", a)) } 's' => { - let a = ap.get::<usize>(); + let a = ap.get::<*const c_char>(); found_percent = false; - w.write_str(str::from_utf8_unchecked(platform::c_str( - a as *const c_char, - ))) + w.write_str(str::from_utf8_unchecked(platform::c_str(a))) } 'u' => { let a = ap.get::<c_uint>(); diff --git a/src/stdlib/src/lib.rs b/src/stdlib/src/lib.rs index 0bc5eb012faccdc78a5f6cc0f6ef06717340a167..1afe2638e99a8b324157763c975dfbc412db63b9 100644 --- a/src/stdlib/src/lib.rs +++ b/src/stdlib/src/lib.rs @@ -229,7 +229,7 @@ pub extern "C" fn erand(xsubi: [c_ushort; 3]) -> c_double { } #[no_mangle] -pub unsafe extern "C" fn exit(status: c_int) -> ! { +pub unsafe extern "C" fn exit(status: c_int) { for i in (0..ATEXIT_FUNCS.len()).rev() { if let Some(func) = ATEXIT_FUNCS[i] { (func)(); diff --git a/src/string/src/lib.rs b/src/string/src/lib.rs index 0caeb823ad2cd52f94411f369d0d67b66e148979..0c627a86129e090442eb167d608c0e2ada2af9cf 100644 --- a/src/string/src/lib.rs +++ b/src/string/src/lib.rs @@ -126,14 +126,13 @@ pub unsafe extern "C" fn strcat(s1: *mut c_char, s2: *const c_char) -> *mut c_ch } #[no_mangle] -pub unsafe extern "C" fn strchr(s: *const c_char, c: c_int) -> *mut c_char { - let c = c as i8; - let mut i = 0; - while *s.offset(i) != 0 { - if *s.offset(i) == c { - return s.offset(i) as *mut c_char; +pub unsafe extern "C" fn strchr(mut s: *const c_char, c: c_int) -> *mut c_char { + let c = c as c_char; + while *s != 0 { + if *s == c { + return s as *mut c_char; } - i += 1; + s = s.offset(1); } ptr::null_mut() } @@ -276,7 +275,7 @@ pub unsafe extern "C" fn strncpy(s1: *mut c_char, s2: *const c_char, n: usize) - } // if length of s2 < n, pad s1 with zeroes - for _ in cmp::min(n, s2_len)..n { + while idx < s2_len { *s1.offset(idx as isize) = 0; idx += 1; } diff --git a/src/strings/Cargo.toml b/src/strings/Cargo.toml new file mode 100644 index 0000000000000000000000000000000000000000..24e75867a8f66eaeac96f93536ea162ab4297254 --- /dev/null +++ b/src/strings/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "strings" +version = "0.1.0" +authors = ["jD91mZM2 <me@krake.one>"] +build = "build.rs" + +[build-dependencies] +cbindgen = { path = "../../cbindgen" } + +[dependencies] +platform = { path = "../platform" } diff --git a/src/strings/build.rs b/src/strings/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..574237034f7eb4648bcad866510068b950cd612d --- /dev/null +++ b/src/strings/build.rs @@ -0,0 +1,11 @@ +extern crate cbindgen; + +use std::{env, fs}; + +fn main() { + let crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); + fs::create_dir_all("../../target/include").expect("failed to create include directory"); + cbindgen::generate(crate_dir) + .expect("failed to generate bindings") + .write_to_file("../../target/include/strings.h"); +} diff --git a/src/strings/cbindgen.toml b/src/strings/cbindgen.toml new file mode 100644 index 0000000000000000000000000000000000000000..d1c7851d7c7dd3247b8f0c28c775ad921b8b11eb --- /dev/null +++ b/src/strings/cbindgen.toml @@ -0,0 +1,7 @@ +sys_includes = ["stddef.h", "stdint.h"] +include_guard = "_STRINGS_H" +language = "C" +style = "Tag" + +[enum] +prefix_with_name = true diff --git a/src/strings/src/lib.rs b/src/strings/src/lib.rs new file mode 100644 index 0000000000000000000000000000000000000000..98ac565c093e5fdf56e57fd9a3b332eadbb97909 --- /dev/null +++ b/src/strings/src/lib.rs @@ -0,0 +1,136 @@ +//! strings implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/strings.h.html +#![no_std] +#![feature(alloc)] + +extern crate alloc; +extern crate platform; + +use alloc::Vec; +use core::ptr; +use platform::types::*; + +#[no_mangle] +pub unsafe extern "C" fn bcmp(mut first: *const c_void, mut second: *const c_void, n: size_t) -> c_int { + let first = first as *const c_char; + let second = second as *const c_char; + + for i in 0..n as isize { + if *first.offset(i) != *second.offset(i) { + return -1; + } + } + 0 +} + +#[no_mangle] +pub unsafe extern "C" fn bcopy(src: *const c_void, dst: *mut c_void, n: size_t) { + let src = src as *mut c_char; + let dst = dst as *mut c_char; + + let mut tmp = Vec::with_capacity(n); + for i in 0..n as isize { + tmp.push(*src.offset(i)); + } + for (i, val) in tmp.into_iter().enumerate() { + *dst.offset(i as isize) = val; + } +} + +#[no_mangle] +pub unsafe extern "C" fn bzero(src: *mut c_void, n: size_t) { + let src = src as *mut c_char; + + for i in 0..n as isize { + *src.offset(i) = 0; + } +} + +#[no_mangle] +pub extern "C" fn ffs(mut i: c_int) -> c_int { + if i == 0 { + return 0; + } + let mut n = 1; + while i & 1 == 0 { + i >>= 1; + n += 1; + } + n +} + +#[no_mangle] +pub unsafe extern "C" fn index(mut s: *const c_char, c: c_int) -> *mut c_char { + while *s != 0 { + if *s == c as c_char { + // Input is const but output is mutable. WHY C, WHY DO THIS? + return s as *mut c_char; + } + s = s.offset(1); + } + ptr::null_mut() +} + +#[no_mangle] +pub unsafe extern "C" fn rindex(mut s: *const c_char, c: c_int) -> *mut c_char { + let original = s; + while *s != 0 { + s = s.offset(1); + } + + while s != original { + s = s.offset(-1); + if *s == c as c_char { + // Input is const but output is mutable. WHY C, WHY DO THIS? + return s as *mut c_char; + } + } + ptr::null_mut() +} + +#[no_mangle] +pub unsafe extern "C" fn strcasecmp(mut first: *const c_char, mut second: *const c_char) -> c_int { + while *first != 0 && *second != 0 { + let mut i = *first; + let mut j = *second; + + if i >= b'A' as c_char && i <= b'Z' as c_char { + i += (b'a' - b'A') as c_char; + } + if j >= b'A' as c_char && j <= b'Z' as c_char { + j += (b'a' - b'A') as c_char; + } + + if i != j { + return -1; + } + + first = first.offset(1); + second = first.offset(1); + } + // Both strings ended at the same time too + (*first == *second) as c_int +} +#[no_mangle] +pub unsafe extern "C" fn strncasecmp(mut first: *const c_char, mut second: *const c_char, mut n: size_t) -> c_int { + while *first != 0 && *second != 0 && n > 0 { + let mut i = *first; + let mut j = *second; + + if i >= b'A' as c_char && i <= b'Z' as c_char { + i += (b'a' - b'A') as c_char; + } + if j >= b'A' as c_char && j <= b'Z' as c_char { + j += (b'a' - b'A') as c_char; + } + + if i != j { + return -1; + } + + first = first.offset(1); + second = first.offset(1); + n -= 1; + } + // Both strings ended at the same time too + (n == 0 || *first == *second) as c_int +} diff --git a/src/sys_socket/src/lib.rs b/src/sys_socket/src/lib.rs index c7c0b5f2bca242700e727bab1645ff7853dd6ecd..20ff30f16dad1043ab14e0c6e033d9bc9948615c 100644 --- a/src/sys_socket/src/lib.rs +++ b/src/sys_socket/src/lib.rs @@ -5,17 +5,26 @@ extern crate platform; +use core::ptr; use platform::types::*; +pub type in_addr_t = [u8; 4]; +pub type in_port_t = u16; pub type sa_family_t = u16; pub type socklen_t = u32; #[repr(C)] pub struct sockaddr { pub sa_family: sa_family_t, - pub sa_data: [c_char; 14], + data: [c_char; 14] } +pub const AF_INET: c_int = 2; +pub const SOCK_STREAM: c_int = 1; +pub const SOCK_DGRAM: c_int = 2; +pub const SOCK_NONBLOCK: c_int = 0o4000; +pub const SOCK_CLOEXEC: c_int = 0o2000000; + #[no_mangle] pub unsafe extern "C" fn accept( socket: c_int, @@ -31,7 +40,7 @@ pub unsafe extern "C" fn bind( address: *const sockaddr, address_len: socklen_t, ) -> c_int { - unimplemented!(); + platform::bind(socket, address as *const platform::sockaddr, address_len) } #[no_mangle] @@ -40,7 +49,7 @@ pub unsafe extern "C" fn connect( address: *const sockaddr, address_len: socklen_t, ) -> c_int { - unimplemented!(); + platform::connect(socket, address as *const platform::sockaddr, address_len) } #[no_mangle] @@ -84,7 +93,7 @@ pub unsafe extern "C" fn recv( length: size_t, flags: c_int, ) -> ssize_t { - unimplemented!(); + recvfrom(socket, buffer, length, flags, ptr::null_mut(), ptr::null_mut()) } #[no_mangle] @@ -96,7 +105,7 @@ pub unsafe extern "C" fn recvfrom( address: *mut sockaddr, address_len: *mut socklen_t, ) -> ssize_t { - unimplemented!(); + platform::recvfrom(socket, buffer, length, flags, address as *mut platform::sockaddr, address_len) } #[no_mangle] @@ -106,11 +115,11 @@ pub unsafe extern "C" fn send( length: size_t, flags: c_int, ) -> ssize_t { - unimplemented!(); + sendto(socket, message, length, flags, ptr::null(), 0) } #[no_mangle] -pub unsafe extern "C" fn sento( +pub unsafe extern "C" fn sendto( socket: c_int, message: *const c_void, length: size_t, @@ -118,7 +127,7 @@ pub unsafe extern "C" fn sento( dest_addr: *const sockaddr, dest_len: socklen_t, ) -> ssize_t { - unimplemented!(); + platform::sendto(socket, message, length, flags, dest_addr as *const platform::sockaddr, dest_len) } #[no_mangle] @@ -138,8 +147,8 @@ pub unsafe extern "C" fn shutdown(socket: c_int, how: c_int) -> c_int { } #[no_mangle] -pub unsafe extern "C" fn socket(domain: c_int, _type: c_int, protocol: c_int) -> c_int { - unimplemented!(); +pub unsafe extern "C" fn socket(domain: c_int, kind: c_int, protocol: c_int) -> c_int { + platform::socket(domain, kind, protocol) } #[no_mangle] diff --git a/tests/.gitignore b/tests/.gitignore index e2242ca6a691e06861fcc4b710cd1e059094cf01..afb0d2f8cf4ffe78458e002639e43e12b68db0aa 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -32,6 +32,7 @@ /setjmp /sleep /sprintf +/strings /stdlib/a64l /stdlib/bsearch /stdlib/mktemp diff --git a/tests/Makefile b/tests/Makefile index 3588a66a5b164d4eaa9e81e6388aba3f01e1d5a2..0957b27f2c6a3c84d09c49d1ceaa7bdc36e62c31 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -26,6 +26,7 @@ EXPECT_BINS=\ setjmp \ sleep \ sprintf \ + strings \ stdio/fwrite \ stdio/all \ stdio/freopen \ @@ -116,4 +117,4 @@ TAILLIBS=\ ../target/openlibm/libopenlibm.a %: %.c $(HEADLIBS) $(TAILLIBS) - gcc -fno-stack-protector -Wall -g $(CFLAGS) $(HEADLIBS) "$<" $(TAILLIBS) -o "$@" + gcc -fno-builtin -fno-stack-protector -Wall -g $(CFLAGS) $(HEADLIBS) "$<" $(TAILLIBS) -o "$@" diff --git a/tests/expected/string/strchr.stdout b/tests/expected/string/strchr.stdout index 5a72f0ea5c79b91a7f2263eca9295643f818f052..02c9cb95513c0d01fd7bef1436c96e5891215fd0 100644 --- a/tests/expected/string/strchr.stdout +++ b/tests/expected/string/strchr.stdout @@ -1,3 +1,3 @@ ello ld - +1 diff --git a/tests/expected/strings.stderr b/tests/expected/strings.stderr new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/expected/strings.stdout b/tests/expected/strings.stdout new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/string/strchr.c b/tests/string/strchr.c index 929c22bede3537694eb577e5ba15c4d76fb9dffb..202737faac070340016b0ae714b49bcae2880588 100644 --- a/tests/string/strchr.c +++ b/tests/string/strchr.c @@ -4,7 +4,7 @@ int main(int argc, char* argv[]) { printf("%s\n", strchr("hello", 'e')); // should be ello printf("%s\n", strchr("world", 'l')); // should be ld - printf("%s\n", strchr("world", 0)); // should be '' + printf("%i\n", strchr("world", 0) == NULL); // should be 1 return 0; } diff --git a/tests/strings.c b/tests/strings.c new file mode 100644 index 0000000000000000000000000000000000000000..2423b900371d949a27cf0283e56c42d29dbbd90c --- /dev/null +++ b/tests/strings.c @@ -0,0 +1,30 @@ +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <strings.h> + +int main() { + assert(!bcmp("hello", "hehe", 2)); + assert(bcmp("hello", "haha", 2)); + + char* new = malloc(3); + bcopy("hi", new, 3); // include nul byte + + assert(!strcasecmp("hi", new)); + assert(!strcasecmp("hi", "HI")); + assert(!strncasecmp("hi", "HIHI", 2)); + + bzero(new, 1); + assert(*new == 0); + assert(*(new+1) == 'i'); + assert(*(new+2) == 0); + + assert(ffs(1) == 1); + assert(ffs(2) == 2); + assert(ffs(3) == 1); + assert(ffs(10) == 2); + + char* str = "hihih"; + assert(index(str, 'i') == str + 1); + assert(rindex(str, 'i') == str + 3); +}