Add 'init/' from commit '0e7a0d3ab46817915180adbbb775c76d67fee31c'
git-subtree-dir: init git-subtree-mainline:57f2dca267git-subtree-split:0e7a0d3ab4
This commit is contained in:
@@ -0,0 +1 @@
|
||||
/target/
|
||||
Generated
+42
@@ -0,0 +1,42 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "init"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"libredox",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.159"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "init"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
libredox = "0.1"
|
||||
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 Redox OS
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,30 @@
|
||||
# RedoxOS init
|
||||
This repository contains the init system for RedoxOS.
|
||||
|
||||
Init is currently being rewritten to support a couple of behaviors that are helpful for running a configurable and robust system. These include:
|
||||
- Dependency relationships between services
|
||||
- Parallel service startup and shutdown
|
||||
- Configuration files for each service, including:
|
||||
- Dependencies
|
||||
- Methods
|
||||
- TODO: Users/Groups for services
|
||||
- TODO: Scheme namespaces for services
|
||||
- Service management
|
||||
- Enable and disable services
|
||||
- Restart failed services
|
||||
|
||||
## How To Contribute
|
||||
|
||||
To learn how to contribute to this system component you need to read the following document:
|
||||
|
||||
- [CONTRIBUTING.md](https://gitlab.redox-os.org/redox-os/redox/-/blob/master/CONTRIBUTING.md)
|
||||
|
||||
## Development
|
||||
|
||||
To learn how to do development with this system component inside the Redox build system you need to read the [Build System](https://doc.redox-os.org/book/build-system-reference.html) and [Coding and Building](https://doc.redox-os.org/book/coding-and-building.html) pages.
|
||||
|
||||
### How To Build
|
||||
|
||||
To build this system component you need to download the Redox build system, you can learn how to do it on the [Building Redox](https://doc.redox-os.org/book/podman-build.html) page.
|
||||
|
||||
This is necessary because they only work with cross-compilation to a Redox virtual machine, but you can do some testing from Linux.
|
||||
@@ -0,0 +1,230 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::env;
|
||||
use std::ffi::CString;
|
||||
use std::fs::{read_dir, File};
|
||||
use std::io::{BufRead, BufReader, Result, Write};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use libredox::error::Error as OsError;
|
||||
|
||||
use libredox::flag::{O_RDONLY, O_WRONLY};
|
||||
|
||||
fn set_default_scheme(scheme: &str) -> std::result::Result<(), OsError> {
|
||||
use std::ffi::{c_char, c_int};
|
||||
|
||||
extern "C" {
|
||||
fn set_default_scheme(scheme: *const c_char) -> c_int;
|
||||
}
|
||||
|
||||
let cstr =
|
||||
CString::new(scheme.as_bytes()).expect(&format!("init: invalid default scheme {}", scheme));
|
||||
|
||||
let res = unsafe { set_default_scheme(cstr.as_ptr()) };
|
||||
|
||||
match res {
|
||||
0 => Ok(()),
|
||||
error_code => Err(OsError::new(error_code)),
|
||||
}
|
||||
}
|
||||
|
||||
fn switch_stdio(stdio: &str) -> Result<()> {
|
||||
let stdin = libredox::Fd::open(stdio, O_RDONLY, 0)?;
|
||||
let stdout = libredox::Fd::open(stdio, O_WRONLY, 0)?;
|
||||
let stderr = libredox::Fd::open(stdio, O_WRONLY, 0)?;
|
||||
|
||||
stdin.dup2(0, &[])?;
|
||||
stdout.dup2(1, &[])?;
|
||||
stderr.dup2(2, &[])?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run(file: &Path) -> Result<()> {
|
||||
let file = File::open(file)?;
|
||||
let reader = BufReader::new(file);
|
||||
for line_res in reader.lines() {
|
||||
let line_raw = line_res?;
|
||||
let line = line_raw.trim();
|
||||
if !line.is_empty() && !line.starts_with('#') {
|
||||
let mut args = line.split(' ').map(|arg| {
|
||||
if arg.starts_with('$') {
|
||||
env::var(&arg[1..]).unwrap_or(String::new())
|
||||
} else {
|
||||
arg.to_string()
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(cmd) = args.next() {
|
||||
match cmd.as_str() {
|
||||
"cd" => {
|
||||
if let Some(dir) = args.next() {
|
||||
if let Err(err) = env::set_current_dir(&dir) {
|
||||
println!("init: failed to cd to '{}': {}", dir, err);
|
||||
}
|
||||
} else {
|
||||
println!("init: failed to cd: no argument");
|
||||
}
|
||||
}
|
||||
"set-default-scheme" => {
|
||||
if let Some(scheme) = args.next() {
|
||||
if let Err(err) = set_default_scheme(&scheme) {
|
||||
println!(
|
||||
"init: failed to set default scheme to '{}': {}",
|
||||
scheme, err
|
||||
);
|
||||
}
|
||||
} else {
|
||||
println!("init: failed to set default scheme: no argument");
|
||||
}
|
||||
}
|
||||
"echo" => {
|
||||
if let Some(arg) = args.next() {
|
||||
print!("{}", arg);
|
||||
}
|
||||
for arg in args {
|
||||
print!(" {}", arg);
|
||||
}
|
||||
print!("\n");
|
||||
}
|
||||
"export" => {
|
||||
if let Some(var) = args.next() {
|
||||
let mut value = String::new();
|
||||
if let Some(arg) = args.next() {
|
||||
value.push_str(&arg);
|
||||
}
|
||||
for arg in args {
|
||||
value.push(' ');
|
||||
value.push_str(&arg);
|
||||
}
|
||||
env::set_var(var, value);
|
||||
} else {
|
||||
println!("init: failed to export: no argument");
|
||||
}
|
||||
}
|
||||
"run" => {
|
||||
if let Some(new_file) = args.next() {
|
||||
if let Err(err) = run(&Path::new(&new_file)) {
|
||||
println!("init: failed to run '{}': {}", new_file, err);
|
||||
}
|
||||
} else {
|
||||
println!("init: failed to run: no argument");
|
||||
}
|
||||
}
|
||||
"run.d" => {
|
||||
// This must be a BTreeMap to iterate in sorted order.
|
||||
let mut entries = BTreeMap::new();
|
||||
let mut missing_arg = true;
|
||||
|
||||
for new_dir in args {
|
||||
if !Path::new(&new_dir).exists() {
|
||||
// Skip non-existent dirs
|
||||
continue;
|
||||
}
|
||||
missing_arg = false;
|
||||
|
||||
match read_dir(&new_dir) {
|
||||
Ok(list) => {
|
||||
for entry_res in list {
|
||||
match entry_res {
|
||||
Ok(entry) => {
|
||||
// This intentionally overwrites older entries with
|
||||
// the same filename to allow overriding entries in
|
||||
// one search dir with those in a later search dir.
|
||||
entries.insert(entry.file_name(), entry.path());
|
||||
}
|
||||
Err(err) => {
|
||||
println!(
|
||||
"init: failed to run.d: '{}': {}",
|
||||
new_dir, err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("init: failed to run.d: '{}': {}", new_dir, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if missing_arg {
|
||||
println!(
|
||||
"init: failed to run.d: no argument or all dirs are non-existent"
|
||||
);
|
||||
} else {
|
||||
// This takes advantage of BTreeMap iterating in sorted order.
|
||||
for (_, entry_path) in entries {
|
||||
if let Err(err) = run(&entry_path) {
|
||||
println!(
|
||||
"init: failed to run '{}': {}",
|
||||
entry_path.display(),
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"stdio" => {
|
||||
if let Some(stdio) = args.next() {
|
||||
if let Err(err) = switch_stdio(&stdio) {
|
||||
println!("init: failed to switch stdio to '{}': {}", stdio, err);
|
||||
}
|
||||
} else {
|
||||
println!("init: failed to set stdio: no argument");
|
||||
}
|
||||
}
|
||||
"unset" => {
|
||||
for arg in args {
|
||||
env::remove_var(&arg);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let mut command = Command::new(cmd.clone());
|
||||
for arg in args {
|
||||
command.arg(arg);
|
||||
}
|
||||
|
||||
match command.spawn() {
|
||||
Ok(child) => match child.wait_with_output() {
|
||||
Ok(output) => {
|
||||
std::io::stdout()
|
||||
.write_all(output.stdout.as_slice())
|
||||
.unwrap();
|
||||
std::io::stderr()
|
||||
.write_all(output.stderr.as_slice())
|
||||
.unwrap();
|
||||
println!("{cmd} done.");
|
||||
}
|
||||
Err(err) => {
|
||||
println!("init: failed to wait for '{}': {}", line, err)
|
||||
}
|
||||
},
|
||||
Err(err) => println!("init: failed to execute '{}': {}", line, err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
if let Err(err) = set_default_scheme("initfs") {
|
||||
println!("init: failed to set default scheme: {}", err);
|
||||
}
|
||||
|
||||
let config = "/etc/init.rc";
|
||||
if let Err(err) = run(&Path::new(config)) {
|
||||
println!("init: failed to run {}: {}", config, err);
|
||||
}
|
||||
|
||||
libredox::call::setrens(0, 0).expect("init: failed to enter null namespace");
|
||||
|
||||
loop {
|
||||
let mut status = 0;
|
||||
libredox::call::waitpid(0, &mut status, 0).unwrap();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user