RustForge

rust-kernel

Rustbelt: a hobby x86_64 kernel written in Rust

rust-kernel / user / getty.rs
1788 bytes ยท raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
//! getty [-1] DEVICE -- run a shell on another terminal, e.g. /dev/hvc0.
//!
//! Real Unix systems run one "getty" per terminal line: it opens the line
//! and starts a login shell on it. Ours skips the login: it opens DEVICE
//! and spawns `sh` with stdin, stdout and stderr all on it. When the shell
//! exits (`exit`) a new one starts, unless `-1` was given.
//!
//! Try it: `getty /dev/hvc0 &` here, then on the host
//! `socat - UNIX-CONNECT:target/hvc0.sock` and type commands. That shell
//! is not "interactive" (no line editing): it reads one line at a time and
//! prints each line after the prompt, like a script.
#![no_std]
#![no_main]

#[macro_use]
#[path = "ulib.rs"]
mod ulib;

use ulib::*;

const SHELL: &str = "/mnt/disk0/bin/sh";

fn main() -> i64 {
    let (once, dev) = match (arg(1), arg(2)) {
        (Some("-1"), Some(dev)) => (true, dev),
        (Some(dev), None) if dev != "-1" => (false, dev),
        _ => {
            eprintln!("usage: getty [-1] DEVICE   (e.g. getty /dev/hvc0 &)");
            return 2;
        }
    };
    loop {
        let fd = open(dev, 0);
        if fd < 0 {
            eprintln!("getty: {}: {}", dev, strerror(fd));
            return 1;
        }
        let greeting = "\nRustbelt getty: shell on this terminal (type `exit` to end it)\n";
        write(fd, greeting.as_bytes());
        let opts = SpawnOptions { stdin: fd, stdout: fd, stderr: fd, flags: 0 };
        let pid = spawn(SHELL, "sh", &opts);
        if pid < 0 {
            eprintln!("getty: {}: {}", SHELL, strerror(pid));
            close(fd);
            return 1;
        }
        let status = wait(pid);
        close(fd);
        if once {
            return status;
        }
        sleep_ms(500); // don't spin if the shell keeps dying at once
    }
}