main.rs 3.36 KB
Newer Older
1
//#![deny(warnings)]
2

3 4 5 6 7 8 9
extern crate failure;
extern crate generational_arena;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
extern crate simple_logger;
Jeremy Soller's avatar
Jeremy Soller committed
10
extern crate syscall;
11 12 13
extern crate toml;

mod dependency;
SamwiseFilmore's avatar
SamwiseFilmore committed
14 15
mod dependency_graph;
mod legacy;
16
mod service;
Jeremy Soller's avatar
Jeremy Soller committed
17

SamwiseFilmore's avatar
SamwiseFilmore committed
18
use std::collections::HashMap;
19
use std::env;
20
use std::fs::{self, File};
SamwiseFilmore's avatar
SamwiseFilmore committed
21
use std::io::{Error, Result};
Jeremy Soller's avatar
Jeremy Soller committed
22
use std::os::unix::io::{AsRawFd, FromRawFd};
23
use std::path::Path;
24

Jeremy Soller's avatar
Jeremy Soller committed
25
use syscall::flag::{O_RDONLY, O_WRONLY};
26

SamwiseFilmore's avatar
SamwiseFilmore committed
27
use dependency::{graph_from_services, start_services};
28 29
use service::services;

30
fn switch_stdio(stdio: &str) -> Result<()> {
Jeremy Soller's avatar
Jeremy Soller committed
31 32 33 34 35 36 37 38 39
    let stdin = unsafe { File::from_raw_fd(
        syscall::open(stdio, O_RDONLY).map_err(|err| Error::from_raw_os_error(err.errno))?
    ) };
    let stdout = unsafe { File::from_raw_fd(
        syscall::open(stdio, O_WRONLY).map_err(|err| Error::from_raw_os_error(err.errno))?
    ) };
    let stderr = unsafe { File::from_raw_fd(
        syscall::open(stdio, O_WRONLY).map_err(|err| Error::from_raw_os_error(err.errno))?
    ) };
40 41

    syscall::dup2(stdin.as_raw_fd(), 0, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?;
42 43
    syscall::dup2(stdout.as_raw_fd(), 1, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?;
    syscall::dup2(stderr.as_raw_fd(), 2, &[]).map_err(|err| Error::from_raw_os_error(err.errno))?;
44 45 46 47

    Ok(())
}

Jeremy Soller's avatar
Jeremy Soller committed
48
pub fn main() {
49 50 51 52 53
    simple_logger::init()
        .unwrap_or_else(|err| {
            println!("init: failed to start logger: {}", err);
        });
    
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    // This way we can continue to support old systems that still have init.rc
    if let Err(_) = fs::metadata("initfs:/etc/init.rc") {
        if let Err(err) = legacy::run(&Path::new("initfs:etc/init.rc")) {
            error!("failed to run initfs:etc/init.rc: {}", err);
        }
    } else {
        let service_list = services("initfs:/etc/init.d")
            .unwrap_or_else(|err| {
                warn!("{}", err);
                vec![]
            });
        
        let service_graph = graph_from_services(service_list);
        let mut provide_hooks = HashMap::with_capacity(2);
        
        provide_hooks.insert("file:".into(), || {
                info!("setting cwd to file:");
                if let Err(err) = env::set_current_dir("file:") {
                    error!("failed to set cwd: {}", err);
                }
                
                info!("setting PATH=file:/bin");
                env::set_var("PATH", "file:/bin");
                
                let fs_services = services("/etc/init.d")
                    .unwrap_or_else(|err| {
                        warn!("{}", err);
                        vec![]
                    });
                
                dependency::graph_add_services(&mut service_graph, fs_services);
                start_services(service_graph, HashMap::new());
            });
        provide_hooks.insert("display:".into(), || {
                switch_stdio("display:1")
                    .unwrap_or_else(|err| {
                        warn!("{}", err);
                    });
            });
        
        info!("setting PATH=initfs:/bin");
        env::set_var("PATH", "initfs:/bin");
        
        start_services(service_graph, provide_hooks);
    }
99
    
Jeremy Soller's avatar
Jeremy Soller committed
100
    syscall::setrens(0, 0).expect("init: failed to enter null namespace");
101
    
102 103 104 105
    loop {
        let mut status = 0;
        syscall::waitpid(0, &mut status, 0).unwrap();
    }
106
}