libc/colors: non-blocking local socket + fixed string bugs in libc
This commit is contained in:
parent
7fdc57fd9f
commit
43acdb9e13
@ -129,7 +129,7 @@ impl SocketWrapper {
|
|||||||
non_blocking: bool,
|
non_blocking: bool,
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
if non_blocking {
|
if non_blocking {
|
||||||
todo!()
|
self.inner.clone().send_nonblocking(message)
|
||||||
} else {
|
} else {
|
||||||
let timeout = self.options.read().send_timeout;
|
let timeout = self.options.read().send_timeout;
|
||||||
block!(self.inner.clone().send_message(message, timeout).await)?
|
block!(self.inner.clone().send_message(message, timeout).await)?
|
||||||
|
@ -102,3 +102,7 @@ pub fn set_file_option_with<'de, T: OptionValue<'de>>(
|
|||||||
let len = T::store(value, buffer)?;
|
let len = T::store(value, buffer)?;
|
||||||
unsafe { crate::sys::set_file_option(fd, T::VARIANT.into(), &buffer[..len]) }
|
unsafe { crate::sys::set_file_option(fd, T::VARIANT.into(), &buffer[..len]) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_nonblocking(fd: RawFd, nonblocking: bool) -> Result<(), Error> {
|
||||||
|
set_file_option::<options::NonBlocking>(fd, &nonblocking)
|
||||||
|
}
|
||||||
|
16
test.c
16
test.c
@ -1,16 +1,12 @@
|
|||||||
|
#include <string.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
struct Dl_info dl0, dl1;
|
char buffer[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||||
|
strncpy(buffer, "abcdefghijkl", sizeof(buffer));
|
||||||
dladdr(main, &dl0);
|
for (int i = 0; i < sizeof(buffer); ++i) {
|
||||||
dladdr(printf, &dl1);
|
printf("[%d] 0x%hhx\n", i, buffer[i]);
|
||||||
printf("%s: %p\n", dl1.dli_sname, dl1.dli_saddr);
|
}
|
||||||
printf("%s @ %p\n", dl1.dli_fname, dl1.dli_fbase);
|
|
||||||
|
|
||||||
printf("%s: %p\n", dl0.dli_sname, dl0.dli_saddr);
|
|
||||||
printf("%s @ %p\n", dl0.dli_fname, dl0.dli_fbase);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,8 @@ impl InputState {
|
|||||||
b'.' => b'>',
|
b'.' => b'>',
|
||||||
b'`' => b'~',
|
b'`' => b'~',
|
||||||
b'\\' => b'|',
|
b'\\' => b'|',
|
||||||
|
b'[' => b'{',
|
||||||
|
b']' => b'}',
|
||||||
_ => ch,
|
_ => ch,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ use std::{
|
|||||||
use cross::mem::SharedMemory;
|
use cross::mem::SharedMemory;
|
||||||
use input::InputState;
|
use input::InputState;
|
||||||
use libcolors::{
|
use libcolors::{
|
||||||
event::{EventData, KeyModifiers, KeyboardKeyEvent, WindowEvent, WindowInfo},
|
event::{EventData, KeyEvent, KeyModifiers, KeyboardKeyEvent, WindowEvent, WindowInfo},
|
||||||
input::Key,
|
input::Key,
|
||||||
message::{ClientMessage, CreateWindowInfo, WindowType},
|
message::{ClientMessage, CreateWindowInfo, WindowType},
|
||||||
};
|
};
|
||||||
@ -67,7 +67,7 @@ impl<'a> Server<'a> {
|
|||||||
surface: &mut DisplaySurface,
|
surface: &mut DisplaySurface,
|
||||||
tx: &mut ServerSender,
|
tx: &mut ServerSender,
|
||||||
peer: &PeerAddress,
|
peer: &PeerAddress,
|
||||||
info: CreateWindowInfo
|
info: CreateWindowInfo,
|
||||||
) -> Result<(WindowInfo, RawFd), Error> {
|
) -> Result<(WindowInfo, RawFd), Error> {
|
||||||
let wid = self.last_window_id;
|
let wid = self.last_window_id;
|
||||||
self.last_window_id += 1;
|
self.last_window_id += 1;
|
||||||
@ -152,17 +152,22 @@ impl<'a> Server<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_window(&mut self, surface: &mut DisplaySurface, tx: &mut ServerSender, direction: Direction) {
|
fn move_window(
|
||||||
|
&mut self,
|
||||||
|
surface: &mut DisplaySurface,
|
||||||
|
tx: &mut ServerSender,
|
||||||
|
direction: Direction,
|
||||||
|
) {
|
||||||
if self.workspace.move_window(direction) {
|
if self.workspace.move_window(direction) {
|
||||||
surface.fill(self.background);
|
surface.fill(self.background);
|
||||||
self.flush_dirty_frames(tx);
|
self.flush_dirty_frames(tx);
|
||||||
self.workspace.all_windows().for_each(|(wid, _)| {
|
self.workspace.all_windows().for_each(|(wid, _)| {
|
||||||
if let Some(window) = self.windows.get(&wid) {
|
if let Some(window) = self.windows.get(&wid) {
|
||||||
tx.send_event(
|
tx.send_event(
|
||||||
EventData::WindowEvent(wid, WindowEvent::RedrawRequested),
|
EventData::WindowEvent(wid, WindowEvent::RedrawRequested),
|
||||||
&window.peer,
|
&window.peer,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,7 +197,8 @@ impl<'a> Server<'a> {
|
|||||||
|
|
||||||
impl WindowServer for Server<'_> {
|
impl WindowServer for Server<'_> {
|
||||||
fn handle_initial(&mut self, mut surface: DisplaySurface) {
|
fn handle_initial(&mut self, mut surface: DisplaySurface) {
|
||||||
self.workspace.resize(surface.width() as u32, surface.height() as u32);
|
self.workspace
|
||||||
|
.resize(surface.width() as u32, surface.height() as u32);
|
||||||
surface.fill(self.background);
|
surface.fill(self.background);
|
||||||
surface.present();
|
surface.present();
|
||||||
|
|
||||||
@ -285,9 +291,9 @@ impl WindowServer for Server<'_> {
|
|||||||
) {
|
) {
|
||||||
self.input_state.update(event.key, event.state);
|
self.input_state.update(event.key, event.state);
|
||||||
|
|
||||||
if event.state {
|
let input = self.input_state.make_input(event.key);
|
||||||
let input = self.input_state.make_input(event.key);
|
|
||||||
|
|
||||||
|
if event.state {
|
||||||
// Non-window keys
|
// Non-window keys
|
||||||
#[allow(clippy::single_match)]
|
#[allow(clippy::single_match)]
|
||||||
match (input.modifiers, input.key) {
|
match (input.modifiers, input.key) {
|
||||||
@ -299,11 +305,6 @@ impl WindowServer for Server<'_> {
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
let focus = self.workspace.focused_window().and_then(|wid| {
|
|
||||||
let window = self.windows.get(&wid)?;
|
|
||||||
Some((wid, window))
|
|
||||||
});
|
|
||||||
|
|
||||||
match (input.modifiers, input.key) {
|
match (input.modifiers, input.key) {
|
||||||
(KeyModifiers::ALT, Key::Char(b'l')) => {
|
(KeyModifiers::ALT, Key::Char(b'l')) => {
|
||||||
self.move_focus(tx, Direction::Right);
|
self.move_focus(tx, Direction::Right);
|
||||||
@ -344,14 +345,6 @@ impl WindowServer for Server<'_> {
|
|||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((wid, window)) = focus {
|
|
||||||
// Deliver event to the window
|
|
||||||
tx.send_event(
|
|
||||||
EventData::WindowEvent(wid, WindowEvent::KeyInput(input)),
|
|
||||||
&window.peer,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// // Window keys
|
// // Window keys
|
||||||
// if let Some((row, col)) = self.focused_frame {
|
// if let Some((row, col)) = self.focused_frame {
|
||||||
// let row_len = self.rows[row].frames.len();
|
// let row_len = self.rows[row].frames.len();
|
||||||
@ -361,6 +354,42 @@ impl WindowServer for Server<'_> {
|
|||||||
// self.focused_frame = None;
|
// self.focused_frame = None;
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let focus = self.workspace.focused_window().and_then(|wid| {
|
||||||
|
let window = self.windows.get(&wid)?;
|
||||||
|
Some((wid, window))
|
||||||
|
});
|
||||||
|
if let Some((wid, window)) = focus {
|
||||||
|
if event.state {
|
||||||
|
tx.send_event(
|
||||||
|
EventData::WindowEvent(
|
||||||
|
wid,
|
||||||
|
WindowEvent::KeyPressed(KeyEvent {
|
||||||
|
key: event.key,
|
||||||
|
modifiers: input.modifiers,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
&window.peer,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Deliver event to the window
|
||||||
|
tx.send_event(
|
||||||
|
EventData::WindowEvent(wid, WindowEvent::KeyInput(input)),
|
||||||
|
&window.peer,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
tx.send_event(
|
||||||
|
EventData::WindowEvent(
|
||||||
|
wid,
|
||||||
|
WindowEvent::KeyReleased(KeyEvent {
|
||||||
|
key: event.key,
|
||||||
|
modifiers: input.modifiers,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
&window.peer,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
)]
|
)]
|
||||||
#![allow(clippy::new_without_default, clippy::missing_transmute_annotations)]
|
#![allow(clippy::new_without_default, clippy::missing_transmute_annotations)]
|
||||||
|
|
||||||
use std::{mem::MaybeUninit, process::ExitCode};
|
use std::{fs, mem::MaybeUninit, os::yggdrasil::real_binary_path, path::Path, process::ExitCode};
|
||||||
|
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use object::Object;
|
use object::Object;
|
||||||
@ -27,7 +27,8 @@ pub mod thread_local;
|
|||||||
|
|
||||||
static mut OBJECTS: MaybeUninit<ObjectSet> = MaybeUninit::uninit();
|
static mut OBJECTS: MaybeUninit<ObjectSet> = MaybeUninit::uninit();
|
||||||
|
|
||||||
fn run(binary: &str, args: &[String]) -> Result<!, Error> {
|
fn run(binary: &Path, args: &[String]) -> Result<!, Error> {
|
||||||
|
log::info!("dyn-loader {binary:?}");
|
||||||
// Open root and its dependencies
|
// Open root and its dependencies
|
||||||
let root = Object::open(binary, true)?;
|
let root = Object::open(binary, true)?;
|
||||||
let mut objects = ObjectSet::new(root);
|
let mut objects = ObjectSet::new(root);
|
||||||
@ -139,6 +140,13 @@ unsafe fn enter(entry: extern "C" fn(usize), argument: usize) -> ! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn real_binary(arg0: &str) -> &Path {
|
||||||
|
if fs::exists(arg0).unwrap_or(false) {
|
||||||
|
return arg0.as_ref();
|
||||||
|
}
|
||||||
|
real_binary_path()
|
||||||
|
}
|
||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
logsink::setup_logging(false);
|
logsink::setup_logging(false);
|
||||||
let args: Vec<String> = std::env::args().skip(1).collect();
|
let args: Vec<String> = std::env::args().skip(1).collect();
|
||||||
@ -148,7 +156,9 @@ fn main() -> ExitCode {
|
|||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
let Err(error) = run(&args[0], &args);
|
let real_binary = real_binary(&args[0]);
|
||||||
|
|
||||||
|
let Err(error) = run(real_binary, &args);
|
||||||
eprintln!("Error: {error}");
|
eprintln!("Error: {error}");
|
||||||
ExitCode::FAILURE
|
ExitCode::FAILURE
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
use std::{
|
use std::{
|
||||||
cmp, collections::HashMap, ffi::{CStr, CString}, fs::File, io::{BufReader, Read, Seek, SeekFrom}, mem, ops::Range, path::{Path, PathBuf}, ptr, rc::Rc
|
cmp,
|
||||||
|
ffi::{CStr, CString},
|
||||||
|
fs::File,
|
||||||
|
io::{BufReader, Read, Seek, SeekFrom},
|
||||||
|
mem,
|
||||||
|
ops::Range,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
ptr,
|
||||||
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use elf::{
|
use elf::{
|
||||||
|
@ -42,7 +42,7 @@ impl Relocation for Rela {
|
|||||||
R_X86_64_TPOFF64 => {
|
R_X86_64_TPOFF64 => {
|
||||||
// Need to extract fixed global offset
|
// Need to extract fixed global offset
|
||||||
let tls_layout = state.tls_layout.as_ref().unwrap();
|
let tls_layout = state.tls_layout.as_ref().unwrap();
|
||||||
log::info!("TPOFF64: module_id={}", tls.module_id);
|
log::info!("TPOFF64: {name} -> module_id={}", tls.module_id);
|
||||||
// Offset from TLS start
|
// Offset from TLS start
|
||||||
let offset = tls_layout.offset(tls.module_id, tls.offset).unwrap();
|
let offset = tls_layout.offset(tls.module_id, tls.offset).unwrap();
|
||||||
let offset_from_tp = -((tls_layout.tp_offset - offset) as i64);
|
let offset_from_tp = -((tls_layout.tp_offset - offset) as i64);
|
||||||
|
@ -1 +1 @@
|
|||||||
export PATH=/bin:/sbin
|
export PATH=/mnt/bin:/bin:/sbin
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
.section .text
|
.section .text
|
||||||
.global _start
|
.global _start
|
||||||
_start:
|
_start:
|
||||||
jmp .
|
mov $12, %rax
|
||||||
|
mov $123, %rdi
|
||||||
|
syscall
|
||||||
|
@ -1,3 +1,10 @@
|
|||||||
void _start(void) {
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
printf("Argument count: %d\n", argc);
|
||||||
|
for (int i = 0; i < argc; ++i) {
|
||||||
|
printf("Argument %d is %s\n", i, argv[i]);
|
||||||
|
}
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
6
userspace/etc/test.cpp
Normal file
6
userspace/etc/test.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
std::cout << "Test!!!" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,4 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
|
/sbin/mount -t ext2 /dev/vb0p1 /mnt
|
||||||
/mnt/bin/clang -cc1as -filetype obj -main-file-name test.S -target-cpu x86-64 -mrelocation-model pic -triple x86_64-unknown-yggdrasil -o /test.o /etc/test.S
|
/mnt/bin/clang -cc1as -filetype obj -main-file-name test.S -target-cpu x86-64 -mrelocation-model pic -triple x86_64-unknown-yggdrasil -o /test.o /etc/test.S
|
||||||
|
/mnt/bin/ld.lld -nostdlib -o /test /test.o
|
||||||
/bin/ls -lh /
|
/bin/ls -lh /
|
||||||
|
|
||||||
|
@ -32,6 +32,10 @@ impl LocalPacketSocket {
|
|||||||
sys::LocalPacketSocketImpl::bind(path).map(Self)
|
sys::LocalPacketSocketImpl::bind(path).map(Self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_nonblocking(&self, nb: bool) -> io::Result<()> {
|
||||||
|
self.0.set_nonblocking(nb)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn receive(&self, buffer: &mut [u8]) -> io::Result<usize> {
|
pub fn receive(&self, buffer: &mut [u8]) -> io::Result<usize> {
|
||||||
self.0.receive(buffer)
|
self.0.receive(buffer)
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,8 @@ pub(crate) trait LocalPacketSocket: AsRawFd + Sized {
|
|||||||
fn bind<P: AsRef<Path>>(path: P) -> io::Result<Self>;
|
fn bind<P: AsRef<Path>>(path: P) -> io::Result<Self>;
|
||||||
fn connect<P: AsRef<Path>>(path: P) -> io::Result<Self>;
|
fn connect<P: AsRef<Path>>(path: P) -> io::Result<Self>;
|
||||||
|
|
||||||
|
fn set_nonblocking(&self, nb: bool) -> io::Result<()>;
|
||||||
|
|
||||||
fn receive(&self, data: &mut [u8]) -> io::Result<usize>;
|
fn receive(&self, data: &mut [u8]) -> io::Result<usize>;
|
||||||
fn receive_from(&self, data: &mut [u8]) -> io::Result<(usize, Self::OwnedAddress)>;
|
fn receive_from(&self, data: &mut [u8]) -> io::Result<(usize, Self::OwnedAddress)>;
|
||||||
fn receive_with_ancillary(&self, data: &mut [u8]) -> io::Result<(usize, Option<OwnedFd>)>;
|
fn receive_with_ancillary(&self, data: &mut [u8]) -> io::Result<(usize, Option<OwnedFd>)>;
|
||||||
|
@ -111,6 +111,11 @@ impl LocalPacketSocket for LocalPacketSocketImpl {
|
|||||||
Ok(this)
|
Ok(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_nonblocking(&self, nb: bool) -> io::Result<()> {
|
||||||
|
runtime::rt::io::set_nonblocking(self.as_raw_fd(), nb)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn receive(&self, data: &mut [u8]) -> io::Result<usize> {
|
fn receive(&self, data: &mut [u8]) -> io::Result<usize> {
|
||||||
let len = yggdrasil_rt::net::socket::receive(self.as_raw_fd(), data)?;
|
let len = yggdrasil_rt::net::socket::receive(self.as_raw_fd(), data)?;
|
||||||
Ok(len)
|
Ok(len)
|
||||||
|
@ -25,6 +25,7 @@ pub struct Connection {
|
|||||||
impl Connection {
|
impl Connection {
|
||||||
pub fn new() -> Result<Self, Error> {
|
pub fn new() -> Result<Self, Error> {
|
||||||
let channel = Channel::connect(crate::CHANNEL_NAME)?;
|
let channel = Channel::connect(crate::CHANNEL_NAME)?;
|
||||||
|
channel.set_nonblocking(true)?;
|
||||||
let (sender, receiver) = channel.split();
|
let (sender, receiver) = channel.split();
|
||||||
let timeout = Duration::from_secs(1);
|
let timeout = Duration::from_secs(1);
|
||||||
let mut poll = Poll::new()?;
|
let mut poll = Poll::new()?;
|
||||||
@ -63,6 +64,21 @@ impl Connection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn poll_event(&mut self) -> Result<Option<Event>, Error> {
|
||||||
|
if let Some(event) = self.event_queue.pop_front() {
|
||||||
|
return Ok(Some(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
match self.receiver.receive_with_file_from() {
|
||||||
|
Ok((data, file, _)) => {
|
||||||
|
let ServerMessage::Event(data) = data;
|
||||||
|
Ok(Some(Event { data, file }))
|
||||||
|
}
|
||||||
|
Err(error) if error.is_would_block() => Ok(None),
|
||||||
|
Err(error) => Err(error.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn receive_event(&mut self) -> Result<Event, Error> {
|
pub fn receive_event(&mut self) -> Result<Event, Error> {
|
||||||
if let Some(event) = self.event_queue.pop_front() {
|
if let Some(event) = self.event_queue.pop_front() {
|
||||||
return Ok(event);
|
return Ok(event);
|
||||||
|
@ -52,7 +52,7 @@ impl<'a> Application<'a> {
|
|||||||
|
|
||||||
fn run_inner(mut self) -> Result<ExitCode, Error> {
|
fn run_inner(mut self) -> Result<ExitCode, Error> {
|
||||||
while self.is_running() {
|
while self.is_running() {
|
||||||
self.poll_events()?;
|
self.wait_events()?;
|
||||||
}
|
}
|
||||||
Ok(ExitCode::SUCCESS)
|
Ok(ExitCode::SUCCESS)
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ impl<'a> Application<'a> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_events(&mut self) -> Result<(), Error> {
|
pub fn wait_events(&mut self) -> Result<(), Error> {
|
||||||
let event = {
|
let event = {
|
||||||
let mut connection = self.connection.lock().unwrap();
|
let mut connection = self.connection.lock().unwrap();
|
||||||
connection.receive_event()?
|
connection.receive_event()?
|
||||||
@ -86,6 +86,22 @@ impl<'a> Application<'a> {
|
|||||||
self.handle_event(event)
|
self.handle_event(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn poll_events(&mut self) -> Result<(), Error> {
|
||||||
|
loop {
|
||||||
|
let event = {
|
||||||
|
let mut connection = self.connection.lock().unwrap();
|
||||||
|
match connection.poll_event() {
|
||||||
|
Ok(Some(event)) => event,
|
||||||
|
Ok(None) => break,
|
||||||
|
Err(error) => return Err(error),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.handle_event(event)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run(self) -> ExitCode {
|
pub fn run(self) -> ExitCode {
|
||||||
match self.run_inner() {
|
match self.run_inner() {
|
||||||
Ok(exit) => exit,
|
Ok(exit) => exit,
|
||||||
|
@ -4,7 +4,7 @@ use cross::mem::FileMapping;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::Error,
|
error::Error,
|
||||||
event::{EventData, KeyInput, WindowEvent},
|
event::{EventData, KeyEvent, KeyInput, WindowEvent},
|
||||||
message::{ClientMessage, CreateWindowInfo},
|
message::{ClientMessage, CreateWindowInfo},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -14,6 +14,8 @@ pub trait OnCloseRequested = Fn() -> EventOutcome;
|
|||||||
pub trait OnKeyInput = Fn(KeyInput) -> EventOutcome;
|
pub trait OnKeyInput = Fn(KeyInput) -> EventOutcome;
|
||||||
pub trait OnResized = Fn(u32, u32) -> EventOutcome;
|
pub trait OnResized = Fn(u32, u32) -> EventOutcome;
|
||||||
pub trait OnFocusChanged = Fn(bool) -> EventOutcome;
|
pub trait OnFocusChanged = Fn(bool) -> EventOutcome;
|
||||||
|
pub trait OnKeyPressed = Fn(KeyEvent) -> EventOutcome;
|
||||||
|
pub trait OnKeyReleased = Fn(KeyEvent) -> EventOutcome;
|
||||||
|
|
||||||
pub trait OnRedrawRequested = Fn(&mut [u32], u32, u32);
|
pub trait OnRedrawRequested = Fn(&mut [u32], u32, u32);
|
||||||
|
|
||||||
@ -38,6 +40,8 @@ pub struct Window<'a> {
|
|||||||
on_key_input: Box<dyn OnKeyInput>,
|
on_key_input: Box<dyn OnKeyInput>,
|
||||||
on_resized: Box<dyn OnResized>,
|
on_resized: Box<dyn OnResized>,
|
||||||
on_focus_changed: Box<dyn OnFocusChanged>,
|
on_focus_changed: Box<dyn OnFocusChanged>,
|
||||||
|
on_key_pressed: Box<dyn OnKeyPressed>,
|
||||||
|
on_key_released: Box<dyn OnKeyReleased>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Window<'a> {
|
impl<'a> Window<'a> {
|
||||||
@ -64,6 +68,8 @@ impl<'a> Window<'a> {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
log::info!("Created window: #{}", create_info.window_id);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
connection: application.connection.clone(),
|
connection: application.connection.clone(),
|
||||||
window_id: create_info.window_id,
|
window_id: create_info.window_id,
|
||||||
@ -82,6 +88,8 @@ impl<'a> Window<'a> {
|
|||||||
dt.fill(0xFF888888);
|
dt.fill(0xFF888888);
|
||||||
}),
|
}),
|
||||||
on_key_input: Box::new(|_ev| EventOutcome::None),
|
on_key_input: Box::new(|_ev| EventOutcome::None),
|
||||||
|
on_key_pressed: Box::new(|_| EventOutcome::None),
|
||||||
|
on_key_released: Box::new(|_| EventOutcome::None),
|
||||||
on_resized: Box::new(|_w, _h| EventOutcome::Redraw),
|
on_resized: Box::new(|_w, _h| EventOutcome::Redraw),
|
||||||
on_focus_changed: Box::new(|_| EventOutcome::None),
|
on_focus_changed: Box::new(|_| EventOutcome::None),
|
||||||
})
|
})
|
||||||
@ -99,6 +107,14 @@ impl<'a> Window<'a> {
|
|||||||
self.on_key_input = Box::new(handler);
|
self.on_key_input = Box::new(handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_on_key_pressed<H: OnKeyPressed + 'static>(&mut self, handler: H) {
|
||||||
|
self.on_key_pressed = Box::new(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_on_key_released<H: OnKeyReleased + 'static>(&mut self, handler: H) {
|
||||||
|
self.on_key_released = Box::new(handler);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_on_resized<H: OnResized + 'static>(&mut self, handler: H) {
|
pub fn set_on_resized<H: OnResized + 'static>(&mut self, handler: H) {
|
||||||
self.on_resized = Box::new(handler);
|
self.on_resized = Box::new(handler);
|
||||||
}
|
}
|
||||||
@ -147,6 +163,8 @@ impl<'a> Window<'a> {
|
|||||||
|
|
||||||
(self.on_resized)(width, height)
|
(self.on_resized)(width, height)
|
||||||
}
|
}
|
||||||
|
WindowEvent::KeyPressed(key) => (self.on_key_pressed)(key),
|
||||||
|
WindowEvent::KeyReleased(key) => (self.on_key_released)(key),
|
||||||
WindowEvent::KeyInput(input) => (self.on_key_input)(input),
|
WindowEvent::KeyInput(input) => (self.on_key_input)(input),
|
||||||
WindowEvent::FocusChanged(focused) => {
|
WindowEvent::FocusChanged(focused) => {
|
||||||
self.focused = focused;
|
self.focused = focused;
|
||||||
|
@ -33,6 +33,15 @@ pub struct Receiver<T> {
|
|||||||
_pd: PhantomData<T>,
|
_pd: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Error {
|
||||||
|
pub fn is_would_block(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Io(error) if error.kind() == io::ErrorKind::WouldBlock => true,
|
||||||
|
_ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PeerAddress(OwnedLocalAddress);
|
pub struct PeerAddress(OwnedLocalAddress);
|
||||||
@ -48,6 +57,11 @@ impl Channel {
|
|||||||
Ok(Self(socket))
|
Ok(Self(socket))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_nonblocking(&self, nb: bool) -> Result<(), Error> {
|
||||||
|
self.0.set_nonblocking(nb)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn split<T: Serialize, U: DeserializeOwned>(self) -> (Sender<T>, Receiver<U>) {
|
pub fn split<T: Serialize, U: DeserializeOwned>(self) -> (Sender<T>, Receiver<U>) {
|
||||||
let this = Arc::new(self);
|
let this = Arc::new(self);
|
||||||
let sender = Sender {
|
let sender = Sender {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef _YGGDRASIL_SYS_WAIT_H
|
#ifndef _YGGDRASIL_SYS_WAIT_H
|
||||||
#define _YGGDRASIL_SYS_WAIT_H 1
|
#define _YGGDRASIL_SYS_WAIT_H 1
|
||||||
|
|
||||||
|
// see headers/sys_wait/mod.rs
|
||||||
|
|
||||||
#define WEXITSTATUS(c) ((int) ((c) & 0xFF))
|
#define WEXITSTATUS(c) ((int) ((c) & 0xFF))
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use core::ffi::{c_int, c_void};
|
use core::ffi::c_void;
|
||||||
|
|
||||||
use crate::{error::CIntZeroResult, process};
|
use crate::{error::CIntZeroResult, process, thread::Thread};
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn __cxa_atexit(
|
unsafe extern "C" fn __cxa_atexit(
|
||||||
@ -14,9 +14,10 @@ unsafe extern "C" fn __cxa_atexit(
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn __cxa_thread_atexit(
|
unsafe extern "C" fn __cxa_thread_atexit(
|
||||||
_destructor: extern "C" fn(*mut c_void),
|
destructor: extern "C" fn(*mut c_void),
|
||||||
_arg: *mut c_void,
|
arg: *mut c_void,
|
||||||
_dso_handle: *mut c_void,
|
dso_handle: *mut c_void,
|
||||||
) -> c_int {
|
) -> CIntZeroResult {
|
||||||
todo!()
|
Thread::at_thread_exit(destructor, arg, dso_handle);
|
||||||
|
CIntZeroResult::SUCCESS
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ pub trait CResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[must_use = "EResult must be converted into its output type with proper errno set"]
|
#[must_use = "EResult must be converted into its output type with proper errno set"]
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum EResult<T> {
|
pub enum EResult<T> {
|
||||||
Ok(T),
|
Ok(T),
|
||||||
Err(Errno),
|
Err(Errno),
|
||||||
|
@ -191,13 +191,16 @@ pub(crate) unsafe extern "C" fn faccessat(
|
|||||||
) -> CIntZeroResult {
|
) -> CIntZeroResult {
|
||||||
let atfd = util::at_fd(atfd)?;
|
let atfd = util::at_fd(atfd)?;
|
||||||
let path = path.ensure_str();
|
let path = path.ensure_str();
|
||||||
let access = match mode {
|
let mut access = AccessMode::empty();
|
||||||
0 => AccessMode::empty(),
|
if mode & R_OK != 0 {
|
||||||
R_OK => AccessMode::READ,
|
access |= AccessMode::READ;
|
||||||
W_OK => AccessMode::WRITE,
|
}
|
||||||
X_OK => AccessMode::EXEC,
|
if mode & W_OK != 0 {
|
||||||
_ => todo!("{mode:#x}"),
|
access |= AccessMode::WRITE;
|
||||||
};
|
}
|
||||||
|
if mode & X_OK != 0 {
|
||||||
|
access |= AccessMode::EXEC;
|
||||||
|
}
|
||||||
syscall::check_access(atfd, path, access).e_map_err(Errno::from)?;
|
syscall::check_access(atfd, path, access).e_map_err(Errno::from)?;
|
||||||
|
|
||||||
CIntZeroResult::SUCCESS
|
CIntZeroResult::SUCCESS
|
||||||
|
@ -119,7 +119,7 @@ unsafe extern "C" fn pthread_mutex_consistent(_mutex: *mut pthread_mutex_t) -> c
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int {
|
unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int {
|
||||||
log::error!("TODO: pthread_mutex_destroy()");
|
log::debug!("TODO: pthread_mutex_destroy()");
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
use core::ffi::{c_char, c_int, c_short, c_void};
|
use core::ffi::{c_char, c_int, c_short, c_void};
|
||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use yggdrasil_rt::{io::RawFd, process::{SpawnFlags, SpawnOption, SpawnOptions}, sys as syscall};
|
use yggdrasil_rt::{
|
||||||
|
io::RawFd,
|
||||||
|
process::{SpawnFlags, SpawnOption, SpawnOptions},
|
||||||
|
sys as syscall,
|
||||||
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
sched::__ygg_sched_param_t,
|
sched::__ygg_sched_param_t,
|
||||||
sys_types::{mode_t, pid_t},
|
sys_types::{mode_t, pid_t},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{CIntCountResult, CIntZeroResult, ResultExt},
|
error::{CIntZeroResult, ResultExt},
|
||||||
headers::errno::Errno,
|
headers::errno::Errno,
|
||||||
util::{NullTerminatedArrayIter, PointerStrExt},
|
util::{NullTerminatedArrayIter, PointerStrExt},
|
||||||
};
|
};
|
||||||
@ -49,9 +53,18 @@ unsafe extern "C" fn posix_spawn(
|
|||||||
environment: &[],
|
environment: &[],
|
||||||
directory: None,
|
directory: None,
|
||||||
optional: &[
|
optional: &[
|
||||||
SpawnOption::CopyFile { source: RawFd::STDIN, child: RawFd::STDIN },
|
SpawnOption::CopyFile {
|
||||||
SpawnOption::CopyFile { source: RawFd::STDOUT, child: RawFd::STDOUT },
|
source: RawFd::STDIN,
|
||||||
SpawnOption::CopyFile { source: RawFd::STDERR, child: RawFd::STDERR },
|
child: RawFd::STDIN,
|
||||||
|
},
|
||||||
|
SpawnOption::CopyFile {
|
||||||
|
source: RawFd::STDOUT,
|
||||||
|
child: RawFd::STDOUT,
|
||||||
|
},
|
||||||
|
SpawnOption::CopyFile {
|
||||||
|
source: RawFd::STDERR,
|
||||||
|
child: RawFd::STDERR,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
flags: SpawnFlags::empty(),
|
flags: SpawnFlags::empty(),
|
||||||
};
|
};
|
||||||
|
@ -56,6 +56,12 @@ impl StringWriter {
|
|||||||
position: 0,
|
position: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn finish(&mut self) {
|
||||||
|
if self.position < self.capacity {
|
||||||
|
unsafe { self.buffer.add(self.position).write(0) };
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Write for StringWriter {
|
impl fmt::Write for StringWriter {
|
||||||
@ -272,5 +278,6 @@ unsafe extern "C" fn vsnprintf(
|
|||||||
let mut writer = StringWriter::new(buffer, capacity);
|
let mut writer = StringWriter::new(buffer, capacity);
|
||||||
let fmt = fmt.ensure_cstr();
|
let fmt = fmt.ensure_cstr();
|
||||||
let count = printf_inner(&mut writer, fmt.to_bytes(), args)?;
|
let count = printf_inner(&mut writer, fmt.to_bytes(), args)?;
|
||||||
|
writer.finish();
|
||||||
CIntCountResult::success(count.try_into().unwrap())
|
CIntCountResult::success(count.try_into().unwrap())
|
||||||
}
|
}
|
||||||
|
@ -66,8 +66,10 @@ unsafe extern "C" fn setkey(_key: *const c_char) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn system(_command: *const c_char) -> CIntZeroResult {
|
unsafe extern "C" fn system(command: *const c_char) -> CIntZeroResult {
|
||||||
todo!()
|
let command = command.ensure_str();
|
||||||
|
log::warn!("system({command:?})");
|
||||||
|
CIntZeroResult::ERROR
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -27,8 +27,9 @@ unsafe extern "C" fn stpncpy(dst: *mut c_char, src: *const c_char, n: usize) ->
|
|||||||
if dst.is_null() || src.is_null() {
|
if dst.is_null() || src.is_null() {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
memset(dst.cast(), 0, n);
|
let dlen = strnlen(src.cast(), n);
|
||||||
mempcpy(dst.cast(), src.cast(), strnlen(src, n)).cast()
|
let r = mempcpy(dst.cast(), src.cast(), n);
|
||||||
|
memset(r.cast(), 0, n - dlen).cast()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@ -164,8 +165,21 @@ unsafe extern "C" fn strncmp(mut a: *const c_char, mut b: *const c_char, mut n:
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn strncpy(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
|
unsafe extern "C" fn strncpy(dst: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
|
||||||
stpncpy(dst, src, n);
|
if dst.is_null() || src.is_null() {
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
let mut i = 0;
|
||||||
|
while i != n {
|
||||||
|
let c = *src.add(i);
|
||||||
|
*dst.add(i) = c;
|
||||||
|
if c == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
dst
|
dst
|
||||||
|
// stpncpy(dst, src, n);
|
||||||
|
// dst
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use core::{
|
use core::{
|
||||||
cmp::Ordering,
|
cmp::Ordering,
|
||||||
ffi::{c_char, c_int},
|
ffi::{c_char, c_int, CStr},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::locale::locale_t;
|
use super::locale::locale_t;
|
||||||
@ -26,6 +26,16 @@ unsafe extern "C" fn strcasecmp_l(
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
|
unsafe extern "C" fn strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
|
||||||
|
if s1.is_null() {
|
||||||
|
if s2.is_null() {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if s2.is_null() {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
for i in 0..n {
|
for i in 0..n {
|
||||||
let c0 = (*s1.add(i) as u8).to_ascii_lowercase();
|
let c0 = (*s1.add(i) as u8).to_ascii_lowercase();
|
||||||
let c1 = (*s2.add(i) as u8).to_ascii_lowercase();
|
let c1 = (*s2.add(i) as u8).to_ascii_lowercase();
|
||||||
|
@ -10,7 +10,7 @@ use yggdrasil_rt::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{self, EResult, ResultExt, TryFromExt},
|
error::{self, CIntZeroResult, CResult, EResult, ResultExt, TryFromExt},
|
||||||
headers::errno::Errno,
|
headers::errno::Errno,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ unsafe fn mmap_inner(
|
|||||||
hint: *mut c_void,
|
hint: *mut c_void,
|
||||||
len: usize,
|
len: usize,
|
||||||
prot: c_int,
|
prot: c_int,
|
||||||
flags: c_int,
|
_flags: c_int,
|
||||||
fd: c_int,
|
fd: c_int,
|
||||||
offset: off_t,
|
offset: off_t,
|
||||||
) -> EResult<NonNull<c_void>> {
|
) -> EResult<NonNull<c_void>> {
|
||||||
@ -73,9 +73,9 @@ unsafe fn mmap_inner(
|
|||||||
if prot & PROT_WRITE != 0 {
|
if prot & PROT_WRITE != 0 {
|
||||||
mapping_flags |= MappingFlags::WRITE;
|
mapping_flags |= MappingFlags::WRITE;
|
||||||
}
|
}
|
||||||
if flags != MAP_PRIVATE {
|
// if flags != MAP_PRIVATE {
|
||||||
todo!("Non-private mappings via mmap(2) are not yet supported");
|
// todo!("Non-private mappings via mmap(2) are not yet supported");
|
||||||
}
|
// }
|
||||||
|
|
||||||
let address = syscall::map_memory(hint, len, mapping_flags, &source).e_map_err(Errno::from)?;
|
let address = syscall::map_memory(hint, len, mapping_flags, &source).e_map_err(Errno::from)?;
|
||||||
assert_ne!(address, 0);
|
assert_ne!(address, 0);
|
||||||
@ -143,8 +143,14 @@ unsafe extern "C" fn mmap(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn munmap(_ptr: *mut c_void, _len: usize) -> c_int {
|
unsafe extern "C" fn munmap(ptr: *mut c_void, len: usize) -> CIntZeroResult {
|
||||||
todo!()
|
let address = ptr.addr();
|
||||||
|
if address == 0 || address == usize::MAX || len == 0 {
|
||||||
|
error::errno = Errno::EINVAL;
|
||||||
|
return CIntZeroResult::ERROR;
|
||||||
|
}
|
||||||
|
syscall::unmap_memory(address, len).e_map_err(Errno::from)?;
|
||||||
|
CIntZeroResult::SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
// posix_***
|
// posix_***
|
||||||
|
@ -10,4 +10,4 @@ usize_type = "size_t"
|
|||||||
isize_type = "ssize_t"
|
isize_type = "ssize_t"
|
||||||
|
|
||||||
[export]
|
[export]
|
||||||
include = ["rlimit", "rusage"]
|
include = ["rlimit", "rusage", "__ygg_rusage_t"]
|
||||||
|
@ -4,6 +4,8 @@ use super::{sys_time::__ygg_timeval_t, sys_types::id_t};
|
|||||||
|
|
||||||
pub type rlim_t = u64;
|
pub type rlim_t = u64;
|
||||||
|
|
||||||
|
pub type __ygg_rusage_t = rusage;
|
||||||
|
|
||||||
pub const PRIO_PROCESS: c_int = 0;
|
pub const PRIO_PROCESS: c_int = 0;
|
||||||
pub const PRIO_PGRP: c_int = 1;
|
pub const PRIO_PGRP: c_int = 1;
|
||||||
pub const PRIO_USER: c_int = 2;
|
pub const PRIO_USER: c_int = 2;
|
||||||
|
@ -73,8 +73,9 @@ impl From<FileAttr> for stat {
|
|||||||
let st_uid = u32::from(value.uid).try_into().unwrap();
|
let st_uid = u32::from(value.uid).try_into().unwrap();
|
||||||
let st_gid = u32::from(value.gid).try_into().unwrap();
|
let st_gid = u32::from(value.gid).try_into().unwrap();
|
||||||
// TODO
|
// TODO
|
||||||
let st_blksize = 512;
|
let st_blksize = value.block_size as _;
|
||||||
let st_blocks = st_size.div_ceil(st_blksize as _).try_into().unwrap();
|
let st_blocks = st_size.div_ceil(st_blksize as _).try_into().unwrap();
|
||||||
|
let st_ino = value.inode.unwrap_or(0) as u64;
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
st_mode,
|
st_mode,
|
||||||
@ -83,6 +84,7 @@ impl From<FileAttr> for stat {
|
|||||||
st_gid,
|
st_gid,
|
||||||
st_blksize,
|
st_blksize,
|
||||||
st_blocks,
|
st_blocks,
|
||||||
|
st_ino,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,14 +127,13 @@ unsafe extern "C" fn mkdir(pathname: *const c_char, mode: mode_t) -> CIntZeroRes
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn mkdirat(atfd: c_int, pathname: *const c_char, mode: mode_t) -> CIntZeroResult {
|
unsafe extern "C" fn mkdirat(atfd: c_int, pathname: *const c_char, mode: mode_t) -> CIntZeroResult {
|
||||||
let _pathname = pathname.ensure_str();
|
let pathname = pathname.ensure_str();
|
||||||
let _atfd = util::at_fd(atfd)?;
|
let atfd = util::at_fd(atfd)?;
|
||||||
let _mode = FileMode::new((mode & 0o777) as u32);
|
let mode = FileMode::new((mode & 0o777) as u32);
|
||||||
|
|
||||||
todo!()
|
io::create_directory(atfd, pathname, mode)?;
|
||||||
// io::create_directory(atfd, pathname, mode)?;
|
|
||||||
|
|
||||||
// CIntZeroResult::OK
|
CIntZeroResult::SUCCESS
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
|
@ -7,6 +7,7 @@ sys_includes = [
|
|||||||
"stdint.h",
|
"stdint.h",
|
||||||
"signal.h",
|
"signal.h",
|
||||||
"sys/types.h",
|
"sys/types.h",
|
||||||
|
"sys/resource.h",
|
||||||
"bits/sys/wait.h"
|
"bits/sys/wait.h"
|
||||||
]
|
]
|
||||||
no_includes = true
|
no_includes = true
|
||||||
|
@ -1,6 +1,18 @@
|
|||||||
use core::ffi::{c_int, c_void};
|
use core::ffi::{c_int, c_void};
|
||||||
|
|
||||||
use super::sys_types::{id_t, pid_t};
|
use yggdrasil_rt::{
|
||||||
|
process::{ExitCode, ProcessGroupId, ProcessId, ProcessWait, WaitFlags},
|
||||||
|
sys as syscall,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::error::{self, EResult, ResultExt};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
errno::Errno,
|
||||||
|
sys_resource::__ygg_rusage_t,
|
||||||
|
sys_time::timeval,
|
||||||
|
sys_types::{id_t, pid_t},
|
||||||
|
};
|
||||||
|
|
||||||
pub const WCONTINUED: c_int = 1 << 0;
|
pub const WCONTINUED: c_int = 1 << 0;
|
||||||
pub const WNOHANG: c_int = 1 << 1;
|
pub const WNOHANG: c_int = 1 << 1;
|
||||||
@ -16,6 +28,45 @@ pub const P_ALL: idtype_t = 0;
|
|||||||
pub const P_PGID: idtype_t = 1;
|
pub const P_PGID: idtype_t = 1;
|
||||||
pub const P_PID: idtype_t = 2;
|
pub const P_PID: idtype_t = 2;
|
||||||
|
|
||||||
|
pub struct WaitResult {
|
||||||
|
pid: ProcessId,
|
||||||
|
status: ExitCode,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait_inner(what: ProcessWait, nonblocking: bool) -> EResult<WaitResult> {
|
||||||
|
let mut status = ExitCode::Exited(0);
|
||||||
|
let mut flags = WaitFlags::empty();
|
||||||
|
if nonblocking {
|
||||||
|
flags |= WaitFlags::NON_BLOCKING;
|
||||||
|
}
|
||||||
|
let pid = unsafe { syscall::wait_process(&what, &mut status, flags) }.e_map_err(Errno::from)?;
|
||||||
|
|
||||||
|
EResult::Ok(WaitResult { pid, status })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn convert_wait_pid(pid: pid_t) -> ProcessWait {
|
||||||
|
// TODO "any child whose process group ID is equal to that of the calling process"
|
||||||
|
if pid > 0 {
|
||||||
|
ProcessWait::Process(unsafe { ProcessId::from_raw(pid as _) })
|
||||||
|
} else if pid == -1 || pid == 0 {
|
||||||
|
ProcessWait::AnyChild
|
||||||
|
} else {
|
||||||
|
let pgrp = (-pid) as u32;
|
||||||
|
ProcessWait::Group(unsafe { ProcessGroupId::from_raw(pgrp) })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_exit_status(code: ExitCode) -> c_int {
|
||||||
|
match code {
|
||||||
|
ExitCode::Exited(status) => status & 0xFF,
|
||||||
|
ExitCode::BySignal(Ok(sig)) => {
|
||||||
|
let signum = sig as u32;
|
||||||
|
(signum + 0x100) as c_int
|
||||||
|
}
|
||||||
|
ExitCode::BySignal(Err(signum)) => (signum + 0x100) as c_int,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
unsafe extern "C" fn wait(_status: *mut c_int) -> pid_t {
|
unsafe extern "C" fn wait(_status: *mut c_int) -> pid_t {
|
||||||
todo!()
|
todo!()
|
||||||
@ -36,3 +87,29 @@ unsafe extern "C" fn waitid(
|
|||||||
unsafe extern "C" fn waitpid(_pid: pid_t, _status: *mut c_int, _options: c_int) -> pid_t {
|
unsafe extern "C" fn waitpid(_pid: pid_t, _status: *mut c_int, _options: c_int) -> pid_t {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
unsafe extern "C" fn wait4(
|
||||||
|
pid: pid_t,
|
||||||
|
wstatus: *mut c_int,
|
||||||
|
options: c_int,
|
||||||
|
rusage: *mut __ygg_rusage_t,
|
||||||
|
) -> pid_t {
|
||||||
|
let pid = convert_wait_pid(pid);
|
||||||
|
let result = match wait_inner(pid, options & WNOHANG != 0) {
|
||||||
|
EResult::Ok(result) => result,
|
||||||
|
EResult::Err(err) => {
|
||||||
|
error::errno = err;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(wstatus) = wstatus.as_mut() {
|
||||||
|
*wstatus = encode_exit_status(result.status);
|
||||||
|
}
|
||||||
|
if let Some(rusage) = rusage.as_mut() {
|
||||||
|
// TODO not implemented on the kernel level
|
||||||
|
rusage.ru_utime = timeval::zero();
|
||||||
|
rusage.ru_stime = timeval::zero();
|
||||||
|
}
|
||||||
|
result.pid.bits() as pid_t
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use core::{ffi::c_int, mem::MaybeUninit};
|
use core::{ffi::c_int, mem::MaybeUninit};
|
||||||
|
|
||||||
use yggdrasil_rt::{
|
use yggdrasil_rt::{
|
||||||
io::{FileAttr, RawFd, SeekFrom}, path::{Path, PathBuf}, sys as syscall
|
io::{FileAttr, FileMode, RawFd, SeekFrom}, path::{Path, PathBuf}, sys as syscall
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -127,6 +127,11 @@ pub fn get_metadata(at: Option<RawFd>, path: &str, follow: bool) -> EResult<File
|
|||||||
EResult::Ok(unsafe { metadata.assume_init() })
|
EResult::Ok(unsafe { metadata.assume_init() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_directory(at: Option<RawFd>, path: &str, mode: FileMode) -> EResult<()> {
|
||||||
|
unsafe { syscall::create_directory(at, path, mode) }?;
|
||||||
|
EResult::Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn realpath<P: AsRef<Path>>(path: P) -> EResult<PathBuf> {
|
pub fn realpath<P: AsRef<Path>>(path: P) -> EResult<PathBuf> {
|
||||||
// Cases:
|
// Cases:
|
||||||
// * /a/b/c -> /a/b/c
|
// * /a/b/c -> /a/b/c
|
||||||
|
@ -34,6 +34,7 @@ use core::{
|
|||||||
|
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use env::environ;
|
use env::environ;
|
||||||
|
use thread::Thread;
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
|
|
||||||
@ -71,6 +72,13 @@ unsafe extern "C" fn __ygglibc_entry(
|
|||||||
signal::init(true);
|
signal::init(true);
|
||||||
init::init();
|
init::init();
|
||||||
|
|
||||||
|
let sp = unsafe {
|
||||||
|
let sp: usize;
|
||||||
|
core::arch::asm!("mov %rsp, {0}", out(reg) sp, options(att_syntax));
|
||||||
|
sp
|
||||||
|
};
|
||||||
|
log::info!("sp = {sp:#x}");
|
||||||
|
|
||||||
// Setup args
|
// Setup args
|
||||||
let args = env::handle_kernel_argument(arg);
|
let args = env::handle_kernel_argument(arg);
|
||||||
let mut c_args = Vec::new();
|
let mut c_args = Vec::new();
|
||||||
@ -86,5 +94,8 @@ unsafe extern "C" fn __ygglibc_entry(
|
|||||||
environ.cast(),
|
environ.cast(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Call main thread dtors
|
||||||
|
Thread::call_thread_dtors();
|
||||||
|
|
||||||
process::c_exit(status)
|
process::c_exit(status)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use core::{ffi::c_void, ptr::null_mut};
|
use core::{cell::RefCell, ffi::c_void, ptr::null_mut};
|
||||||
|
|
||||||
use alloc::{boxed::Box, collections::BTreeMap};
|
use alloc::{boxed::Box, collections::BTreeMap, vec::Vec};
|
||||||
use yggdrasil_rt::{
|
use yggdrasil_rt::{
|
||||||
process::{
|
process::{
|
||||||
thread::{self as rt, ThreadCreateInfo},
|
thread::{self as rt, ThreadCreateInfo},
|
||||||
@ -12,13 +12,21 @@ use yggdrasil_rt::{
|
|||||||
use crate::{
|
use crate::{
|
||||||
error::{EResult, OptionExt},
|
error::{EResult, OptionExt},
|
||||||
headers::{
|
headers::{
|
||||||
errno::Errno, sys_types::{pthread_attr_t, pthread_t}
|
errno::Errno,
|
||||||
|
sys_types::{pthread_attr_t, pthread_t},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod tls;
|
pub mod tls;
|
||||||
|
|
||||||
|
pub struct ThreadDestructor {
|
||||||
|
pub destructor: extern "C" fn(*mut c_void),
|
||||||
|
pub argument: *mut c_void,
|
||||||
|
}
|
||||||
|
|
||||||
static THREADS: Mutex<BTreeMap<pthread_t, Thread>> = Mutex::new(BTreeMap::new());
|
static THREADS: Mutex<BTreeMap<pthread_t, Thread>> = Mutex::new(BTreeMap::new());
|
||||||
|
#[thread_local]
|
||||||
|
static THREAD_LOCAL_DTORS: RefCell<Vec<ThreadDestructor>> = RefCell::new(Vec::new());
|
||||||
|
|
||||||
pub const DEFAULT_STACK_SIZE: usize = 4096 * 16;
|
pub const DEFAULT_STACK_SIZE: usize = 4096 * 16;
|
||||||
pub const DEFAULT_SIGNAL_STACK_SIZE: usize = 4096 * 8;
|
pub const DEFAULT_SIGNAL_STACK_SIZE: usize = 4096 * 8;
|
||||||
@ -49,7 +57,7 @@ impl Thread {
|
|||||||
signal_stack: rt::ThreadSignalStack::Allocate(DEFAULT_SIGNAL_STACK_SIZE),
|
signal_stack: rt::ThreadSignalStack::Allocate(DEFAULT_SIGNAL_STACK_SIZE),
|
||||||
stack,
|
stack,
|
||||||
#[allow(clippy::redundant_closure)]
|
#[allow(clippy::redundant_closure)]
|
||||||
entry: rt::ThreadFunction::Closure(Box::new(move |arg| entry(arg))),
|
entry: rt::ThreadFunction::Closure(Box::new(move |arg| Self::thread_main(entry, arg))),
|
||||||
tls_image: tls::TLS_IMAGE.get().as_ref(),
|
tls_image: tls::TLS_IMAGE.get().as_ref(),
|
||||||
};
|
};
|
||||||
let handle = rt::Thread::spawn(info, argument, true)?;
|
let handle = rt::Thread::spawn(info, argument, true)?;
|
||||||
@ -68,6 +76,32 @@ impl Thread {
|
|||||||
pub fn this() -> EResult<pthread_t> {
|
pub fn this() -> EResult<pthread_t> {
|
||||||
EResult::Ok(unsafe { rt::Thread::<*mut c_void>::current().id() })
|
EResult::Ok(unsafe { rt::Thread::<*mut c_void>::current().id() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn thread_main(
|
||||||
|
entry: extern "C" fn(*mut c_void) -> *mut c_void,
|
||||||
|
arg: *mut c_void,
|
||||||
|
) -> *mut c_void {
|
||||||
|
let ret = entry(arg);
|
||||||
|
unsafe { Self::call_thread_dtors() };
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn at_thread_exit(
|
||||||
|
destructor: extern "C" fn(*mut c_void),
|
||||||
|
argument: *mut c_void,
|
||||||
|
_dso_handle: *mut c_void,
|
||||||
|
) {
|
||||||
|
THREAD_LOCAL_DTORS.borrow_mut().push(ThreadDestructor {
|
||||||
|
destructor,
|
||||||
|
argument,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn call_thread_dtors() {
|
||||||
|
for dtor in THREAD_LOCAL_DTORS.borrow().iter() {
|
||||||
|
(dtor.destructor)(dtor.argument);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_main_thread(arg: &ProgramArgumentInner) {
|
pub fn init_main_thread(arg: &ProgramArgumentInner) {
|
||||||
|
@ -141,7 +141,7 @@ fn lex_identifier(i: &str) -> IResult<&str, &str> {
|
|||||||
recognize(many1_count(alt((alphanumeric1, is_a("-_")))))(i)
|
recognize(many1_count(alt((alphanumeric1, is_a("-_")))))(i)
|
||||||
}
|
}
|
||||||
fn lex_filename(i: &str) -> IResult<&str, &str> {
|
fn lex_filename(i: &str) -> IResult<&str, &str> {
|
||||||
recognize(many1_count(alt((alphanumeric1, is_a("./-_:")))))(i)
|
recognize(many1_count(alt((alphanumeric1, is_a("./-_:+")))))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lex_braced_var(i: &str) -> IResult<&str, &str> {
|
fn lex_braced_var(i: &str) -> IResult<&str, &str> {
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
use std::{io::{stdout, Write}, process::Command};
|
#![feature(seek_stream_len)]
|
||||||
|
|
||||||
|
use std::{fs::File, io::{stdout, Seek, Write}};
|
||||||
|
|
||||||
|
use cross::mem::FileMapping;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let output = Command::new("/bin/ls").output().unwrap();
|
let mut file = File::open("/etc/test.txt").unwrap();
|
||||||
println!("status = {:?}", output.status);
|
let size = file.stream_len().unwrap();
|
||||||
println!("stdout:");
|
let mapping = FileMapping::map(file, size as usize).unwrap();
|
||||||
stdout().write_all(&output.stdout).ok();
|
let mut data = vec![0; size as usize];
|
||||||
println!();
|
data.copy_from_slice(&mapping[..]);
|
||||||
println!("stderr:");
|
stdout().write_all(&data).unwrap();
|
||||||
stdout().write_all(&output.stderr).ok();
|
|
||||||
println!();
|
|
||||||
}
|
}
|
||||||
|
@ -362,6 +362,7 @@ impl Terminal<'_> {
|
|||||||
static ABORT: AtomicBool = AtomicBool::new(false);
|
static ABORT: AtomicBool = AtomicBool::new(false);
|
||||||
|
|
||||||
fn main() -> ExitCode {
|
fn main() -> ExitCode {
|
||||||
|
logsink::setup_logging(false);
|
||||||
let font = PcScreenFont::default();
|
let font = PcScreenFont::default();
|
||||||
let term = Terminal::new(font).unwrap();
|
let term = Terminal::new(font).unwrap();
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#![allow(unused)]
|
||||||
use std::{
|
use std::{
|
||||||
fs,
|
fs,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
@ -126,19 +127,25 @@ fn build_test_c_program(
|
|||||||
fn install_ygglibc(env: &BuildEnv, ygglibc: &Ygglibc) -> Result<(), Error> {
|
fn install_ygglibc(env: &BuildEnv, ygglibc: &Ygglibc) -> Result<(), Error> {
|
||||||
log::info!("Installing ygglibc into LLVM sysroot");
|
log::info!("Installing ygglibc into LLVM sysroot");
|
||||||
|
|
||||||
let dst_lib_dir = env.llvm_sysroot.join("lib");
|
// let dst_lib_dir = env.llvm_sysroot.join("lib");
|
||||||
let dst_include_dir = env.llvm_sysroot.join("usr/include");
|
// let dst_include_dir = env.llvm_sysroot.join("usr/include");
|
||||||
|
let _ = env;
|
||||||
|
let _ = ygglibc.crt0_file;
|
||||||
|
|
||||||
fs::create_dir_all(&dst_lib_dir)?;
|
// fs::create_dir_all(&dst_lib_dir)?;
|
||||||
fs::create_dir_all(&dst_include_dir)?;
|
// fs::create_dir_all(&dst_include_dir)?;
|
||||||
|
|
||||||
fs::copy(&ygglibc.static_lib_file, dst_lib_dir.join("libygglibc.a"))?;
|
// fs::copy(&ygglibc.static_lib_file, dst_lib_dir.join("libygglibc.a"))?;
|
||||||
fs::copy(&ygglibc.shared_lib_file, dst_lib_dir.join("libygglibc.so"))?;
|
// fs::copy(&ygglibc.shared_lib_file, dst_lib_dir.join("libygglibc.so"))?;
|
||||||
fs::copy(&ygglibc.crt0_file, dst_lib_dir.join("crt0.o"))?;
|
// fs::copy(&ygglibc.crt0_file, dst_lib_dir.join("crt0.o"))?;
|
||||||
|
|
||||||
for path in ygglibc.include_paths.iter() {
|
let _ = ygglibc.static_lib_file;
|
||||||
util::copy_dir_recursive(path, &dst_include_dir)?;
|
let _ = ygglibc.shared_lib_file;
|
||||||
}
|
let _ = ygglibc.include_paths;
|
||||||
|
|
||||||
|
// for path in ygglibc.include_paths.iter() {
|
||||||
|
// util::copy_dir_recursive(path, &dst_include_dir)?;
|
||||||
|
// }
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -212,7 +219,8 @@ fn install_openlibm(env: &BuildEnv, libm: &Openlibm) -> Result<(), Error> {
|
|||||||
fs::copy(&libm.static_lib_file, env.llvm_sysroot.join("lib/libm.a"))?;
|
fs::copy(&libm.static_lib_file, env.llvm_sysroot.join("lib/libm.a"))?;
|
||||||
fs::copy(&libm.shared_lib_file, env.llvm_sysroot.join("lib/libm.so"))?;
|
fs::copy(&libm.shared_lib_file, env.llvm_sysroot.join("lib/libm.so"))?;
|
||||||
|
|
||||||
util::copy_dir_recursive(&libm.include_path, env.llvm_sysroot.join("usr/include"))?;
|
let _ = libm.include_path;
|
||||||
|
// util::copy_dir_recursive(&libm.include_path, env.llvm_sysroot.join("usr/include"))?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -241,6 +249,7 @@ pub fn build_c(env: &BuildEnv, install: &mut Vec<(PathBuf, PathBuf)>) -> Result<
|
|||||||
"lib/libc++.so".into(),
|
"lib/libc++.so".into(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
install.push((ygglibc.crt0_file, "lib/crt0.o".into()));
|
||||||
install.push((ygglibc.shared_lib_file, "lib/libygglibc.so".into()));
|
install.push((ygglibc.shared_lib_file, "lib/libygglibc.so".into()));
|
||||||
install.push((libm.shared_lib_file, "lib/libopenlibm.so.4".into()));
|
install.push((libm.shared_lib_file, "lib/libopenlibm.so.4".into()));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user