Commit a6518fd8 authored by SamwiseFilmore's avatar SamwiseFilmore

Implement Dependencies and Services

This is a pretty dirty example of where this project is going, but I'd
like to get something into git for people to look at, and so that I save
it. If you want to run this branch, you need the filesystem.toml found
here: https://gitlab.redox-os.org/snippets/58
parent ed2111b5
Pipeline #2046 failed with stages
in 48 seconds
[[package]]
name = "backtrace"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "backtrace-sys"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "cc"
version = "1.0.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chrono"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "failure"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "failure_derive"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "generational-arena"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "init"
version = "0.1.0"
dependencies = [
"failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
"generational-arena 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
"simple_logger 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"toml 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "log"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-integer"
version = "0.1.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "proc-macro2"
version = "0.4.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "quote"
version = "0.6.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
......@@ -10,5 +128,123 @@ name = "redox_syscall"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rustc-demangle"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde_derive"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "simple_logger"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn"
version = "0.15.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "synstructure"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "toml"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "unicode-xid"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a"
"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0"
"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878"
"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7"
"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596"
"checksum generational-arena 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7519f72ae2a5912271755e9009d4fc72d58e2d901c90f3410cdb66247f606485"
"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311"
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09"
"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c"
"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1"
"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395"
"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef"
"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c"
"checksum simple_logger 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25111f1d77db1ac3ee11b62ba4b7a162e6bb3be43e28273f0d3935cc8d3ff7fb"
"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7"
"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
"checksum toml 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "19782e145d5abefb03758958f06ea35f7b1d8421b534140e0238fd3d0bfd66e3"
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[package]
name = "init"
description = "Init system for redox, includes service management"
version = "0.1.0"
[dependencies]
failure = "0.1"
generational-arena = "0.2"
log = "0.4"
redox_syscall = "0.1"
serde = "1.0"
serde_derive = "1.0"
simple_logger = "1.0"
toml = "0.4"
use std::collections::{HashMap, HashSet};
use generational_arena::{Arena, Index};
use service::Service;
#[derive(Debug)]
pub struct ServiceNode {
pub service: Service,
pub dependencies: Vec<Index>
}
impl ServiceNode {
// Empty dependencies
fn from_service(service: Service) -> ServiceNode {
ServiceNode {
service,
dependencies: vec![]
}
}
}
pub fn build_graph(mut services: Vec<Service>) -> Arena<ServiceNode> {
let mut graph = Arena::with_capacity(services.len());
let services: HashMap<String, Index> = services.drain(..)
.map(|service| (service.name.clone(), graph.insert(ServiceNode::from_service(service))) )
.collect();
for index in services.values() {
let node = graph.get_mut(*index)
.expect("services were just added");
if let Some(ref dependencies) = node.service.dependencies {
for dependency in dependencies.iter() {
match services.get(dependency) {
Some(index) => node.dependencies.push(*index),
// It's not a super big deal if a dependency doesn't exist
None => warn!("dependency not found: {}", dependency)
}
}
}
}
graph
}
/// Naive linear dependency resolution algorithm. The _should_
/// be a solution to the dependency graph. Note that the solution
/// is probably not deterministic.
///
/// # Limitations
/// Not currently detecting dependency cycles
/// Can't figure out
pub fn resolve_linear(graph: &Arena<ServiceNode>) -> Vec<Index> {
let arena_len = graph.len();
let mut resolved = Vec::with_capacity(arena_len);
let mut seen = HashSet::with_capacity(arena_len);
while resolved.len() < arena_len {
for (index, service_node) in graph.iter() {
// formatting?
if (service_node.dependencies.is_empty() ||
service_node.dependencies.iter().all(|index| resolved.contains(index))) &&
!seen.contains(&index) {
seen.insert(index);
resolved.push(index);
}
}
}
resolved
}
#![deny(warnings)]
//#![deny(warnings)]
extern crate failure;
extern crate generational_arena;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate simple_logger;
extern crate syscall;
extern crate toml;
mod dependency;
mod service;
use std::env;
use std::fs::{File, read_dir};
......@@ -8,8 +19,12 @@ use std::io::{Read, Error, Result};
use std::os::unix::io::{AsRawFd, FromRawFd};
use std::path::Path;
use std::process::Command;
use syscall::flag::{O_RDONLY, O_WRONLY};
use dependency::*;
use service::services;
fn switch_stdio(stdio: &str) -> Result<()> {
let stdin = unsafe { File::from_raw_fd(
syscall::open(stdio, O_RDONLY).map_err(|err| Error::from_raw_os_error(err.errno))?
......@@ -137,12 +152,34 @@ pub fn run(file: &Path) -> Result<()> {
}
pub fn main() {
simple_logger::init()
.unwrap_or_else(|err| {
println!("init: failed to start logger: {}", err);
});
let services = services("initfs:/etc/init.d")
.unwrap_or_else(|err| {
warn!("{}", err);
vec![]
});
let services = build_graph(services);
let resolved = resolve_linear(&services);
env::set_var("PATH", "/bin");
for index in resolved.iter() {
let node = services.get(*index).unwrap();
node.service.methods.get("start").unwrap().wait();
}
// This file has had the services removed now
if let Err(err) = run(&Path::new("initfs:etc/init.rc")) {
println!("init: failed to run initfs:etc/init.rc: {}", err);
}
syscall::setrens(0, 0).expect("init: failed to enter null namespace");
loop {
let mut status = 0;
syscall::waitpid(0, &mut status, 0).unwrap();
......
use std::collections::HashMap;
use std::env;
use std::ffi::OsStr;
use std::fs::{File, read_dir};
use std::io::Read;
use std::path::Path;
use std::process::Command;
use failure::Error;
use toml;
#[derive(Debug, Deserialize)]
pub struct Method {
pub cmd: Vec<String>
}
impl Method {
/// Replace any arguments that are environment variables
/// with the value stored in that environment variable
///
/// The `$` must be the first character in the argument
// (Maybe change that)
fn sub_env(&mut self) {
let modified_cmd = self.cmd.drain(..)
.map(|arg| if arg.trim().starts_with('$') {
let (_, varname) = arg.split_at(1);
let val = env::var(varname).unwrap_or(String::new());
println!("{:?}", val);
val
} else {
arg
})
.collect();
self.cmd = modified_cmd;
}
pub fn wait(&self) {
let mut cmd = Command::new(&self.cmd[0]);
cmd.args(self.cmd[1..].iter());
match cmd.spawn() {
Ok(mut child) => match child.wait() {
Ok(_status) => {},
Err(err) => error!("failed to wait for: {:?}: {}", cmd, err)
},
Err(err) => error!("failed to spawn: {:?}: {}", cmd, err)
}
}
}
#[derive(Debug, Deserialize)]
pub struct Service {
#[serde(skip)]
pub name: String,
pub dependencies: Option<Vec<String>>,
pub methods: HashMap<String, Method>
}
impl Service {
/// Parse a service file
pub fn from_file(file_path: impl AsRef<Path>) -> Result<Service, Error> {
let mut data = String::new();
File::open(&file_path)?
.read_to_string(&mut data)?;
let mut service = toml::from_str::<Service>(&data)?;
//BUG: Only removes the portion after the last '.'
service.name = file_path.as_ref().file_stem()
.expect("file name empty") // shouldn't be able to happen
.to_string_lossy() // Redox uses unicode, this should never fail
.into();
service.sub_env();
Ok(service)
}
/// Substitue all fields which support environment variable
/// substitution
fn sub_env(&mut self) {
for method in self.methods.values_mut() {
method.sub_env();
}
}
}
/// Parse all the toml files in a directory as services
pub fn services(dir: impl AsRef<Path>) -> Result<Vec<Service>, Error> {
let mut services = vec![];
for file in read_dir(dir)? {
let file_path = file?.path();
let is_toml = match file_path.extension() {
Some(ext) => ext == OsStr::new("toml"),
None => false
};
if is_toml {
match Service::from_file(file_path) {
Ok(service) => services.push(service),
Err(err) => error!("{}", err)
}
}
}
Ok(services)
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment