init: Allow init to register the scheme for a daemon
Unfortunately the scheme still has to be created by the daemon due to a kernel bug, but once that is fixed, it would allow delayed spawning of scheme daemons.
This commit is contained in:
Generated
+3
@@ -517,6 +517,9 @@ name = "daemon"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"libredox",
|
||||
"redox-scheme",
|
||||
"redox_syscall 0.7.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -5,3 +5,6 @@ edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
libc.workspace = true
|
||||
libredox.workspace = true
|
||||
redox-scheme.workspace = true
|
||||
redox_syscall.workspace = true
|
||||
|
||||
+120
-7
@@ -1,19 +1,32 @@
|
||||
#![feature(never_type)]
|
||||
|
||||
use std::io::{self, PipeWriter, Read, Write};
|
||||
use std::os::fd::{AsRawFd, FromRawFd};
|
||||
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::process::Command;
|
||||
|
||||
use libredox::Fd;
|
||||
use redox_scheme::Socket;
|
||||
use redox_scheme::scheme::{SchemeAsync, SchemeSync};
|
||||
|
||||
unsafe fn get_fd(var: &str) -> RawFd {
|
||||
let fd: RawFd = std::env::var(var).unwrap().parse().unwrap();
|
||||
if unsafe { libc::fcntl(fd, libc::F_SETFD, libc::FD_CLOEXEC) } == -1 {
|
||||
panic!(
|
||||
"daemon: failed to set CLOEXEC flag for {var} fd: {}",
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
}
|
||||
fd
|
||||
}
|
||||
|
||||
#[must_use = "Daemon::ready must be called"]
|
||||
pub struct Daemon {
|
||||
write_pipe: PipeWriter,
|
||||
}
|
||||
|
||||
impl Daemon {
|
||||
pub fn new<F: FnOnce(Daemon) -> !>(f: F) -> ! {
|
||||
let write_pipe = unsafe {
|
||||
io::PipeWriter::from_raw_fd(std::env::var("INIT_NOTIFY").unwrap().parse().unwrap())
|
||||
};
|
||||
pub fn new(f: impl FnOnce(Daemon) -> !) -> ! {
|
||||
let write_pipe = unsafe { io::PipeWriter::from_raw_fd(get_fd("INIT_NOTIFY")) };
|
||||
|
||||
f(Daemon { write_pipe })
|
||||
}
|
||||
@@ -25,10 +38,10 @@ impl Daemon {
|
||||
pub fn spawn(mut cmd: Command) {
|
||||
let (mut read_pipe, write_pipe) = io::pipe().unwrap();
|
||||
|
||||
// Pass pipe to child
|
||||
// Pass notify pipe to child
|
||||
if unsafe { libc::fcntl(write_pipe.as_raw_fd(), libc::F_SETFD, 0) } == -1 {
|
||||
eprintln!(
|
||||
"daemon: failed to unset CLOEXEC flag for pipe: {}",
|
||||
"daemon: failed to unset CLOEXEC flag for notify pipe: {}",
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
return;
|
||||
@@ -57,3 +70,103 @@ impl Daemon {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "SchemeDaemon::ready must be called"]
|
||||
pub struct SchemeDaemon {
|
||||
write_pipe: PipeWriter,
|
||||
}
|
||||
|
||||
impl SchemeDaemon {
|
||||
pub fn new(f: impl FnOnce(SchemeDaemon) -> !) -> ! {
|
||||
let write_pipe = unsafe { io::PipeWriter::from_raw_fd(get_fd("INIT_NOTIFY")) };
|
||||
|
||||
f(SchemeDaemon { write_pipe })
|
||||
}
|
||||
|
||||
pub fn ready_with_fd(self, cap_fd: Fd) -> syscall::Result<()> {
|
||||
syscall::call_wo(
|
||||
self.write_pipe.as_raw_fd() as usize,
|
||||
&cap_fd.into_raw().to_ne_bytes(),
|
||||
syscall::CallFlags::FD,
|
||||
&[],
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn ready_sync_scheme<S: SchemeSync>(
|
||||
self,
|
||||
socket: &Socket,
|
||||
scheme: &mut S,
|
||||
) -> syscall::Result<()> {
|
||||
let cap_id = scheme.scheme_root()?;
|
||||
let cap_fd = socket.create_this_scheme_fd(0, cap_id, 0, 0)?;
|
||||
self.ready_with_fd(Fd::new(cap_fd))
|
||||
}
|
||||
|
||||
pub fn ready_async_scheme<S: SchemeAsync>(
|
||||
self,
|
||||
socket: &Socket,
|
||||
scheme: &mut S,
|
||||
) -> syscall::Result<()> {
|
||||
let cap_id = scheme.scheme_root()?;
|
||||
let cap_fd = socket.create_this_scheme_fd(0, cap_id, 0, 0)?;
|
||||
self.ready_with_fd(Fd::new(cap_fd))
|
||||
}
|
||||
|
||||
pub fn spawn(mut cmd: Command, scheme_name: &str) {
|
||||
let (read_pipe, write_pipe) = io::pipe().unwrap();
|
||||
|
||||
// Pass notify pipe to child
|
||||
if unsafe { libc::fcntl(write_pipe.as_raw_fd(), libc::F_SETFD, 0) } == -1 {
|
||||
eprintln!(
|
||||
"daemon: failed to unset CLOEXEC flag for notify pipe: {}",
|
||||
io::Error::last_os_error()
|
||||
);
|
||||
return;
|
||||
}
|
||||
cmd.env("INIT_NOTIFY", format!("{}", write_pipe.as_raw_fd()));
|
||||
|
||||
if let Err(err) = cmd.spawn() {
|
||||
eprintln!("daemon: failed to execute {cmd:?}: {err}");
|
||||
return;
|
||||
}
|
||||
drop(write_pipe);
|
||||
|
||||
let mut new_fd = usize::MAX;
|
||||
let fd_bytes = unsafe {
|
||||
core::slice::from_raw_parts_mut(
|
||||
core::slice::from_mut(&mut new_fd).as_mut_ptr() as *mut u8,
|
||||
core::mem::size_of::<usize>(),
|
||||
)
|
||||
};
|
||||
loop {
|
||||
match syscall::call_ro(
|
||||
read_pipe.as_raw_fd() as usize,
|
||||
fd_bytes,
|
||||
syscall::CallFlags::FD | syscall::CallFlags::FD_UPPER,
|
||||
&[],
|
||||
) {
|
||||
Err(syscall::Error {
|
||||
errno: syscall::EINTR,
|
||||
}) => continue,
|
||||
Ok(0) => {
|
||||
eprintln!("daemon: {cmd:?} exited without notifying readiness");
|
||||
return;
|
||||
}
|
||||
Ok(1) => break,
|
||||
Ok(n) => {
|
||||
eprintln!("daemon: incorrect amount of fds {n} returned");
|
||||
return;
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("daemon: failed to wait for {cmd:?}: {err}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let current_namespace_fd = libredox::call::getns().expect("TODO");
|
||||
libredox::call::register_scheme_to_ns(current_namespace_fd, scheme_name, new_fd)
|
||||
.expect("TODO");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,23 +7,22 @@
|
||||
//! In the future fbbootlogd may also pull from logd as opposed to have logd push logs to it. And it
|
||||
//! it could display a boot splash like plymouth instead of a boot log when booting in quiet mode.
|
||||
|
||||
use std::io::Write;
|
||||
use std::os::fd::AsRawFd;
|
||||
|
||||
use event::EventQueue;
|
||||
use inputd::ConsumerHandleEvent;
|
||||
use libredox::errno::EAGAIN;
|
||||
use orbclient::Event;
|
||||
use redox_scheme::{scheme::register_sync_scheme, RequestKind, SignalBehavior, Socket};
|
||||
use redox_scheme::{RequestKind, SignalBehavior, Socket};
|
||||
|
||||
use crate::scheme::FbbootlogScheme;
|
||||
|
||||
mod scheme;
|
||||
|
||||
fn main() {
|
||||
daemon::Daemon::new(daemon);
|
||||
daemon::SchemeDaemon::new(daemon);
|
||||
}
|
||||
fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
fn daemon(daemon: daemon::SchemeDaemon) -> ! {
|
||||
let event_queue = EventQueue::new().expect("fbbootlogd: failed to create event queue");
|
||||
|
||||
event::user_data! {
|
||||
@@ -58,7 +57,7 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
.create_this_scheme_fd(0, 0, 0, 0)
|
||||
.expect("fbbootlogd: failed to create log fd");
|
||||
// Add ourself as log sink
|
||||
let mut log_file = libredox::Fd::open(
|
||||
let log_file = libredox::Fd::open(
|
||||
"/scheme/log/add_sink",
|
||||
libredox::flag::O_WRONLY | libredox::flag::O_CLOEXEC,
|
||||
0,
|
||||
@@ -69,15 +68,12 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
.expect("fbbootlogd: failed to send log fd to log scheme.");
|
||||
}
|
||||
|
||||
register_sync_scheme(&socket, "fbbootlog", &mut scheme)
|
||||
.expect("fbbootlog: failed to register scheme to namespace");
|
||||
let _ = daemon.ready_sync_scheme(&socket, &mut scheme);
|
||||
|
||||
// This is not possible for now as fbbootlogd needs to open new displays at runtime for graphics
|
||||
// driver handoff. In the future inputd may directly pass a handle to the display instead.
|
||||
//libredox::call::setrens(0, 0).expect("fbbootlogd: failed to enter null namespace");
|
||||
|
||||
daemon.ready();
|
||||
|
||||
for event in event_queue {
|
||||
match event.expect("fbbootlogd: failed to get event").user_data {
|
||||
Source::Scheme => {
|
||||
|
||||
@@ -3,7 +3,7 @@ use inputd::ConsumerHandleEvent;
|
||||
use libredox::errno::{EAGAIN, EINTR};
|
||||
use orbclient::Event;
|
||||
use redox_scheme::{
|
||||
scheme::{register_sync_scheme, Op, SchemeResponse, SchemeSync},
|
||||
scheme::{Op, SchemeResponse, SchemeSync},
|
||||
CallerCtx, RequestKind, Response, SignalBehavior, Socket,
|
||||
};
|
||||
use std::env;
|
||||
@@ -16,9 +16,9 @@ mod scheme;
|
||||
mod text;
|
||||
|
||||
fn main() {
|
||||
daemon::Daemon::new(daemon);
|
||||
daemon::SchemeDaemon::new(daemon);
|
||||
}
|
||||
fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
fn daemon(daemon: daemon::SchemeDaemon) -> ! {
|
||||
let vt_ids = env::args()
|
||||
.skip(1)
|
||||
.map(|arg| arg.parse().expect("invalid vt number"))
|
||||
@@ -46,15 +46,12 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
|
||||
let mut scheme = FbconScheme::new(&vt_ids, &mut event_queue);
|
||||
|
||||
register_sync_scheme(&socket, "fbcon", &mut scheme)
|
||||
.expect("fbcond: failed to register scheme to namespace");
|
||||
let _ = daemon.ready_sync_scheme(&socket, &mut scheme);
|
||||
|
||||
// This is not possible for now as fbcond needs to open new displays at runtime for graphics
|
||||
// driver handoff. In the future inputd may directly pass a handle to the display instead.
|
||||
// libredox::call::setrens(0, 0).expect("fbcond: failed to enter null namespace");
|
||||
|
||||
daemon.ready();
|
||||
|
||||
let mut blocked = Vec::new();
|
||||
|
||||
// Handle all events that could have happened before registering with the event queue.
|
||||
@@ -139,7 +136,7 @@ fn handle_event(
|
||||
RequestKind::Cancellation(cancellation_request) => {
|
||||
if let Some(i) = blocked
|
||||
.iter()
|
||||
.position(|(op, caller)| caller.id == cancellation_request.id)
|
||||
.position(|(_op, caller)| caller.id == cancellation_request.id)
|
||||
{
|
||||
let (blocked_req, _) = blocked.remove(i);
|
||||
let resp = Response::err(EINTR, blocked_req);
|
||||
|
||||
@@ -20,7 +20,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use inputd::{ControlEvent, VtEvent, VtEventKind};
|
||||
|
||||
use libredox::errno::ESTALE;
|
||||
use redox_scheme::scheme::{register_sync_scheme, SchemeSync};
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
use redox_scheme::{CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket};
|
||||
|
||||
use orbclient::{Event, EventOption};
|
||||
@@ -552,13 +552,12 @@ impl SchemeSync for InputScheme {
|
||||
}
|
||||
}
|
||||
|
||||
fn deamon(deamon: daemon::Daemon) -> anyhow::Result<()> {
|
||||
fn deamon(daemon: daemon::SchemeDaemon) -> anyhow::Result<()> {
|
||||
// Create the ":input" scheme.
|
||||
let socket_file = Socket::create()?;
|
||||
let mut scheme = InputScheme::new();
|
||||
|
||||
register_sync_scheme(&socket_file, "input", &mut scheme)?;
|
||||
deamon.ready();
|
||||
let _ = daemon.ready_sync_scheme(&socket_file, &mut scheme);
|
||||
|
||||
loop {
|
||||
scheme.has_new_events = false;
|
||||
@@ -632,7 +631,7 @@ fn deamon(deamon: daemon::Daemon) -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
fn daemon_runner(daemon: daemon::Daemon) -> ! {
|
||||
fn daemon_runner(daemon: daemon::SchemeDaemon) -> ! {
|
||||
deamon(daemon).unwrap();
|
||||
unreachable!();
|
||||
}
|
||||
@@ -697,6 +696,6 @@ fn main() {
|
||||
common::file_level(),
|
||||
);
|
||||
|
||||
daemon::Daemon::new(daemon_runner);
|
||||
daemon::SchemeDaemon::new(daemon_runner);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -4,6 +4,6 @@ export PATH /scheme/initfs/bin
|
||||
export LD_LIBRARY_PATH /scheme/initfs/lib
|
||||
export RUST_BACKTRACE 1
|
||||
rtcd
|
||||
notify nulld
|
||||
notify zerod
|
||||
notify randd
|
||||
scheme null nulld
|
||||
scheme zero zerod
|
||||
scheme rand randd
|
||||
|
||||
+2
-2
@@ -1,3 +1,3 @@
|
||||
notify logd
|
||||
scheme log logd
|
||||
stdio /scheme/log
|
||||
notify ramfs logging
|
||||
scheme logging ramfs logging
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
notify inputd
|
||||
scheme input inputd
|
||||
notify vesad
|
||||
unset FRAMEBUFFER_ADDR FRAMEBUFFER_VIRT FRAMEBUFFER_WIDTH FRAMEBUFFER_HEIGHT FRAMEBUFFER_STRIDE
|
||||
#TODO: unset FRAMEBUFFER1 and beyond?
|
||||
notify fbbootlogd
|
||||
scheme fbbootlog fbbootlogd
|
||||
# Activate framebuffer log VT, which disables kernel graphical debug
|
||||
inputd -A 1
|
||||
notify fbcond 2
|
||||
scheme fbcon fbcond 2
|
||||
|
||||
@@ -124,6 +124,19 @@ fn run_command(cmd: Command, config: &InitConfig) {
|
||||
|
||||
daemon::Daemon::spawn(command);
|
||||
}
|
||||
Command::Scheme(scheme, cmd, args) => {
|
||||
if config.skip_cmd.contains(&cmd) {
|
||||
eprintln!("init: skipping '{} {}'", cmd, args.join(" "));
|
||||
return;
|
||||
}
|
||||
|
||||
let mut command = process::Command::new(&cmd);
|
||||
for arg in args {
|
||||
command.arg(arg);
|
||||
}
|
||||
|
||||
daemon::SchemeDaemon::spawn(command, &scheme);
|
||||
}
|
||||
Command::Regular(cmd, args) => {
|
||||
let mut command = process::Command::new(cmd.clone());
|
||||
for arg in args {
|
||||
|
||||
@@ -37,6 +37,7 @@ pub enum Command {
|
||||
// Service
|
||||
Nowait(String, Vec<String>),
|
||||
Notify(String, Vec<String>),
|
||||
Scheme(String, String, Vec<String>),
|
||||
Regular(String, Vec<String>),
|
||||
|
||||
// Modify env
|
||||
@@ -110,6 +111,16 @@ impl Command {
|
||||
|
||||
Ok(Command::Notify(cmd, args.collect()))
|
||||
}
|
||||
"scheme" => {
|
||||
let Some(scheme) = args.next() else {
|
||||
return Err("init: failed to run scheme: no argument".to_owned());
|
||||
};
|
||||
let Some(cmd) = args.next() else {
|
||||
return Err("init: failed to run scheme: missing command".to_owned());
|
||||
};
|
||||
|
||||
Ok(Command::Scheme(scheme, cmd, args.collect()))
|
||||
}
|
||||
_ => Ok(Command::Regular(cmd, args.collect())),
|
||||
}
|
||||
}
|
||||
|
||||
+4
-10
@@ -1,25 +1,19 @@
|
||||
use redox_scheme::{
|
||||
scheme::{register_sync_scheme, SchemeSync},
|
||||
RequestKind, Response, SignalBehavior, Socket,
|
||||
};
|
||||
use redox_scheme::{scheme::SchemeSync, RequestKind, Response, SignalBehavior, Socket};
|
||||
use std::process;
|
||||
|
||||
use crate::scheme::LogScheme;
|
||||
|
||||
mod scheme;
|
||||
|
||||
fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
fn daemon(daemon: daemon::SchemeDaemon) -> ! {
|
||||
let socket = Socket::create().expect("logd: failed to create log scheme");
|
||||
|
||||
let mut scheme = LogScheme::new(&socket);
|
||||
|
||||
register_sync_scheme(&socket, "log", &mut scheme)
|
||||
.expect("logd: failed to register scheme to namespace");
|
||||
let _ = daemon.ready_sync_scheme(&socket, &mut scheme);
|
||||
|
||||
libredox::call::setrens(0, 0).expect("logd: failed to enter null namespace");
|
||||
|
||||
daemon.ready();
|
||||
|
||||
while let Some(request) = socket
|
||||
.next_request(SignalBehavior::Restart)
|
||||
.expect("logd: failed to read events from log scheme")
|
||||
@@ -50,5 +44,5 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
daemon::Daemon::new(daemon);
|
||||
daemon::SchemeDaemon::new(daemon);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ use std::fs::{File, OpenOptions};
|
||||
use std::io::{Read, Write};
|
||||
use std::mem;
|
||||
use std::os::fd::{FromRawFd, RawFd};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::mpsc::{self, Sender};
|
||||
|
||||
use redox_scheme::scheme::SchemeSync;
|
||||
|
||||
+4
-5
@@ -8,19 +8,18 @@ use redox_scheme::{RequestKind, SignalBehavior};
|
||||
use self::scheme::Scheme;
|
||||
|
||||
fn main() {
|
||||
daemon::Daemon::new(daemon);
|
||||
daemon::SchemeDaemon::new(daemon);
|
||||
}
|
||||
|
||||
fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
fn daemon(daemon: daemon::SchemeDaemon) -> ! {
|
||||
let scheme_name = env::args().nth(1).expect("Usage:\n\tramfs SCHEME_NAME");
|
||||
|
||||
let socket = redox_scheme::Socket::create().expect("ramfs: failed to create socket");
|
||||
|
||||
let mut scheme = Scheme::new(scheme_name.clone()).expect("ramfs: failed to initialize scheme");
|
||||
|
||||
redox_scheme::scheme::register_sync_scheme(&socket, &scheme_name, &mut scheme)
|
||||
.expect("ramfs: failed to register to namespace");
|
||||
daemon.ready();
|
||||
let _ = daemon.ready_sync_scheme(&socket, &mut scheme);
|
||||
|
||||
libredox::call::setrens(0, 0).expect("ramfs: failed to enter null namespace");
|
||||
|
||||
loop {
|
||||
|
||||
+5
-9
@@ -14,13 +14,12 @@ pub const MODE_READ: u16 = 0o4;
|
||||
use raw_cpuid::CpuId;
|
||||
|
||||
use redox_scheme::{
|
||||
scheme::{register_sync_scheme, SchemeSync},
|
||||
CallerCtx, OpenResult, RequestKind, Response, SignalBehavior, Socket,
|
||||
scheme::SchemeSync, CallerCtx, OpenResult, RequestKind, SignalBehavior, Socket,
|
||||
};
|
||||
use syscall::data::Stat;
|
||||
use syscall::flag::{EventFlags, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_WRONLY};
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
use syscall::{Error, Result, EACCES, EBADF, EEXIST, ENOENT, EOPNOTSUPP, EPERM, MODE_CHR};
|
||||
use syscall::{Error, Result, EACCES, EBADF, EEXIST, ENOENT, EPERM, MODE_CHR};
|
||||
|
||||
// Create an RNG Seed to create initial seed from the rdrand intel instruction
|
||||
use rand_core::SeedableRng;
|
||||
@@ -465,15 +464,12 @@ impl SchemeSync for RandScheme {
|
||||
}
|
||||
}
|
||||
|
||||
fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
fn daemon(daemon: daemon::SchemeDaemon) -> ! {
|
||||
let socket = Socket::create().expect("randd: failed to create rand scheme");
|
||||
|
||||
let mut scheme = RandScheme::new();
|
||||
|
||||
register_sync_scheme(&socket, "rand", &mut scheme)
|
||||
.expect("randd: failed to register scheme to namespace");
|
||||
|
||||
daemon.ready();
|
||||
let _ = daemon.ready_sync_scheme(&socket, &mut scheme);
|
||||
|
||||
libredox::call::setrens(0, 0).expect("randd: failed to enter null namespace");
|
||||
|
||||
@@ -497,5 +493,5 @@ fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
daemon::Daemon::new(daemon);
|
||||
daemon::SchemeDaemon::new(daemon);
|
||||
}
|
||||
|
||||
+4
-11
@@ -1,4 +1,4 @@
|
||||
use redox_scheme::{scheme::register_sync_scheme, RequestKind, SignalBehavior, Socket};
|
||||
use redox_scheme::{RequestKind, SignalBehavior, Socket};
|
||||
|
||||
use scheme::ZeroScheme;
|
||||
|
||||
@@ -10,27 +10,20 @@ enum Ty {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
daemon::Daemon::new(daemon);
|
||||
daemon::SchemeDaemon::new(daemon);
|
||||
}
|
||||
|
||||
fn daemon(daemon: daemon::Daemon) -> ! {
|
||||
fn daemon(daemon: daemon::SchemeDaemon) -> ! {
|
||||
let ty = match &*std::env::args().next().unwrap() {
|
||||
"nulld" => Ty::Null,
|
||||
"zerod" => Ty::Zero,
|
||||
_ => panic!("needs to be called as either nulld or zerod"),
|
||||
};
|
||||
|
||||
let name = match ty {
|
||||
Ty::Null => "null",
|
||||
Ty::Zero => "zero",
|
||||
};
|
||||
let socket = Socket::create().expect("zerod: failed to create zero scheme");
|
||||
let mut zero_scheme = ZeroScheme(ty);
|
||||
|
||||
register_sync_scheme(&socket, name, &mut zero_scheme)
|
||||
.expect("zerod: failed to register scheme to namespace");
|
||||
|
||||
daemon.ready();
|
||||
let _ = daemon.ready_sync_scheme(&socket, &mut zero_scheme);
|
||||
|
||||
libredox::call::setrens(0, 0).expect("zerod: failed to enter null namespace");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user