moros 0.12.0

MOROS: Obscure Rust Operating System
Documentation
use crate::api::console::Style;
use crate::api::process::ExitCode;
use crate::api::syscall;
use crate::sys::console;
use crate::sys::fs::OpenFlag;
use crate::usr;

use alloc::format;
use alloc::vec;
use alloc::vec::Vec;
use core::str;
use core::str::FromStr;
use smoltcp::wire::IpAddress;

pub fn main(args: &[&str]) -> Result<(), ExitCode> {
    let mut verbose = false;
    let args: Vec<&str> = args.iter().filter_map(|arg| match *arg {
        "-v" | "--verbose" => {
            verbose = true;
            None
        }
        _ => Some(*arg),
    }).collect();

    if args.len() != 2 {
        help();
        return Err(ExitCode::UsageError);
    }

    let (host, port) = match args[1].split_once(':') {
        Some((h, p)) => (h, p),
        None => {
            help();
            return Err(ExitCode::UsageError);
        }
    };
    let port: u16 = match port.parse() {
        Ok(n) => n,
        Err(_) => {
            eprint!("Could not parse port");
            return Err(ExitCode::UsageError);
        }
    };
    let addr = if host.ends_with(char::is_numeric) {
        IpAddress::from_str(host).expect("invalid address format")
    } else {
        match usr::host::resolve(host) {
            Ok(ip_addr) => ip_addr,
            Err(e) => {
                error!("Could not resolve host {:?}", e);
                return Err(ExitCode::Failure);
            }
        }
    };

    let socket_path = "/dev/net/tcp";
    let buf_len = if let Some(info) = syscall::info(socket_path) {
        info.size() as usize
    } else {
        error!("Could not open '{}'", socket_path);
        return Err(ExitCode::Failure);
    };

    let flags = OpenFlag::Device as u8;
    if let Some(handle) = syscall::open(socket_path, flags) {
        if syscall::connect(handle, addr, port).is_err() {
            error!("Could not connect to {}:{}", addr, port);
            syscall::close(handle);
            return Err(ExitCode::Failure);
        }
        if verbose {
            debug!("Connected to {}:{}", addr, port);
        }
        loop {
            if console::end_of_text() || console::end_of_transmission() {
                eprintln!();
                syscall::close(handle);
                return Err(ExitCode::Failure);
            }
            let mut data = vec![0; buf_len];
            if let Some(bytes) = syscall::read(handle, &mut data) {
                if bytes == 0 {
                    break;
                }
                data.resize(bytes, 0);
                syscall::write(1, &data);
            } else {
                error!("Could not read from {}:{}", addr, port);
                syscall::close(handle);
                return Err(ExitCode::Failure);
            }
        }
        syscall::close(handle);
        Ok(())
    } else {
        Err(ExitCode::Failure)
    }
}

fn help() {
    let csi_option = Style::color("aqua");
    let csi_title = Style::color("yellow");
    let csi_reset = Style::reset();
    println!(
        "{}Usage:{} tcp {}<host>:<port>{1}",
        csi_title, csi_reset, csi_option
    );
}