diff --git a/Makefile b/Makefile index cefe29b..2e7fc51 100644 --- a/Makefile +++ b/Makefile @@ -28,6 +28,7 @@ clean: cargo clean --manifest-path drivers/ps2d/Cargo.toml cargo clean --manifest-path drivers/pcid/Cargo.toml cargo clean --manifest-path drivers/vesad/Cargo.toml + cargo clean --manifest-path programs/getty/Cargo.toml cargo clean --manifest-path programs/init/Cargo.toml cargo clean --manifest-path programs/ion/Cargo.toml cargo clean --manifest-path programs/login/Cargo.toml @@ -274,6 +275,7 @@ $(BUILD)/filesystem.bin: \ coreutils \ extrautils \ schemes \ + filesystem/bin/getty \ filesystem/bin/ion \ filesystem/bin/login \ filesystem/bin/smith diff --git a/filesystem/etc/issue b/filesystem/etc/issue new file mode 100644 index 0000000..3fc86b4 --- /dev/null +++ b/filesystem/etc/issue @@ -0,0 +1,6 @@ +########## Redox OS ########## +# Login with the following: # +# `root` # +# `user`:`password` # +############################## + diff --git a/filesystem/etc/motd b/filesystem/etc/motd new file mode 100644 index 0000000..5cd097a --- /dev/null +++ b/filesystem/etc/motd @@ -0,0 +1,2 @@ +Welcome to Redox OS! + diff --git a/filesystem/etc/passwd b/filesystem/etc/passwd index 2255e55..9c71c96 100644 --- a/filesystem/etc/passwd +++ b/filesystem/etc/passwd @@ -1,2 +1,2 @@ -root;A69F73CCA23A9AC5C8B567DC185A756E97C982164FE25859E0D1DCC1475C80A615B2123AF1F5F94C11E3E9402C3AC558F50199D95B6D3E31758586281DCD26;0;0;root;file:root;file:bin/ion -user;A69F73CCA23A9AC5C8B567DC185A756E97C982164FE25859E0D1DCC1475C80A615B2123AF1F5F94C11E3E9402C3AC558F50199D95B6D3E31758586281DCD26;1000;1000;user;file:home/user;file:bin/ion +root;;0;0;root;file:root;file:bin/ion +user;E9A75486736A55AF4FEA861E237835C4A555A05094DEE1DCA2F68AFEA49CC3A5E8DE6EA131EA521311F4D6FB054A146E8282F8E35FF2E6368C1A62E909716;1000;1000;user;file:home/user;file:bin/ion diff --git a/initfs/etc/init.rc b/initfs/etc/init.rc index 22ae8e4..4ac3e96 100644 --- a/initfs/etc/init.rc +++ b/initfs/etc/init.rc @@ -2,4 +2,4 @@ initfs:bin/pcid initfs:etc/pcid.toml initfs:bin/redoxfs disk:0 file:bin/vesad file:bin/ps2d -file:bin/login display: +file:bin/getty display: diff --git a/programs/getty/Cargo.toml b/programs/getty/Cargo.toml new file mode 100644 index 0000000..49e1459 --- /dev/null +++ b/programs/getty/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "getty" +version = "0.1.0" + +[dependencies] +syscall = { path = "../../syscall/" } diff --git a/programs/getty/src/main.rs b/programs/getty/src/main.rs new file mode 100644 index 0000000..79ce665 --- /dev/null +++ b/programs/getty/src/main.rs @@ -0,0 +1,52 @@ +#![feature(question_mark)] + +extern crate syscall; + +use std::fs::File; +use std::io::{Read, Write}; +use std::process::Command; +use std::{env, io, str, thread}; + +pub fn main() { + let mut args = env::args().skip(1); + + let tty = args.next().expect("getty: no tty provided"); + + let _ = syscall::close(2); + let _ = syscall::close(1); + let _ = syscall::close(0); + + let _ = syscall::open(&tty, syscall::flag::O_RDWR); + let _ = syscall::open(&tty, syscall::flag::O_RDWR); + let _ = syscall::open(&tty, syscall::flag::O_RDWR); + + env::set_current_dir("file:").unwrap(); + + env::set_var("TTY", &tty); + { + let mut path = [0; 4096]; + if let Ok(count) = syscall::fpath(0, &mut path) { + let path_str = str::from_utf8(&path[..count]).unwrap_or(""); + let reference = path_str.split(':').nth(1).unwrap_or(""); + let mut parts = reference.split('/'); + env::set_var("COLUMNS", parts.next().unwrap_or("80")); + env::set_var("LINES", parts.next().unwrap_or("30")); + } + } + + thread::spawn(move || { + let stdout = io::stdout(); + let mut stdout = stdout.lock(); + loop { + stdout.write(b"\x1Bc").unwrap(); + let _ = stdout.flush(); + match Command::new("file:bin/login").spawn() { + Ok(mut child) => match child.wait() { + Ok(_status) => (), //println!("getty: waited for login: {:?}", status.code()), + Err(err) => panic!("getty: failed to wait for login: {}", err) + }, + Err(err) => panic!("getty: failed to execute login: {}", err) + } + } + }); +} diff --git a/programs/login/Cargo.toml b/programs/login/Cargo.toml index a788e32..0462d1b 100644 --- a/programs/login/Cargo.toml +++ b/programs/login/Cargo.toml @@ -3,7 +3,6 @@ name = "login" version = "0.1.0" [dependencies] -syscall = { path = "../../syscall/" } termion = "*" [dependencies.octavo] diff --git a/programs/login/src/main.rs b/programs/login/src/main.rs index 5865c14..c611835 100644 --- a/programs/login/src/main.rs +++ b/programs/login/src/main.rs @@ -1,7 +1,6 @@ #![feature(question_mark)] extern crate octavo; -extern crate syscall; extern crate termion; use octavo::octavo_digest::Digest; @@ -47,48 +46,43 @@ impl<'a> Passwd<'a> { } pub fn main() { - let mut args = env::args().skip(1); + let stdin = io::stdin(); + let mut stdin = stdin.lock(); + let stdout = io::stdout(); + let mut stdout = stdout.lock(); - let tty = args.next().expect("login: no tty provided"); - - let _ = syscall::close(2); - let _ = syscall::close(1); - let _ = syscall::close(0); - - let _ = syscall::open(&tty, syscall::flag::O_RDWR); - let _ = syscall::open(&tty, syscall::flag::O_RDWR); - let _ = syscall::open(&tty, syscall::flag::O_RDWR); - - env::set_current_dir("file:").unwrap(); - - env::set_var("TTY", &tty); - { - let mut path = [0; 4096]; - if let Ok(count) = syscall::fpath(0, &mut path) { - let path_str = str::from_utf8(&path[..count]).unwrap_or(""); - let reference = path_str.split(':').nth(1).unwrap_or(""); - let mut parts = reference.split('/'); - env::set_var("COLUMNS", parts.next().unwrap_or("80")); - env::set_var("LINES", parts.next().unwrap_or("30")); - } + if let Ok(mut issue) = File::open("/etc/issue") { + io::copy(&mut issue, &mut stdout).unwrap(); + let _ = stdout.flush(); } - thread::spawn(move || { - let stdin = io::stdin(); - let mut stdin = stdin.lock(); - let stdout = io::stdout(); - let mut stdout = stdout.lock(); + loop { + stdout.write_all(b"\x1B[1mredox login:\x1B[0m ").unwrap(); + let _ = stdout.flush(); - loop { - stdout.write_all(b"\x1B[1mredox login:\x1B[0m ").unwrap(); - let _ = stdout.flush(); + let user = (&mut stdin as &mut Read).read_line().unwrap().unwrap_or(String::new()); + if ! user.is_empty() { + let mut passwd_string = String::new(); + File::open("file:etc/passwd").unwrap().read_to_string(&mut passwd_string).unwrap(); - let user = (&mut stdin as &mut Read).read_line().unwrap().unwrap_or(String::new()); - if ! user.is_empty() { + let mut passwd_option = None; + for line in passwd_string.lines() { + if let Ok(passwd) = Passwd::parse(line) { + if user == passwd.user && "" == passwd.hash { + passwd_option = Some(passwd); + break; + } + } + } + + if passwd_option.is_none() { stdout.write_all(b"\x1B[1mpassword:\x1B[0m ").unwrap(); let _ = stdout.flush(); if let Some(password) = stdin.read_passwd(&mut stdout).unwrap() { + stdout.write(b"\n").unwrap(); + let _ = stdout.flush(); + let password_hash = { let mut output = vec![0; Sha512::output_bytes()]; let mut hash = Sha512::default(); @@ -101,15 +95,10 @@ pub fn main() { encoded }; - { - let mut debug = File::open("debug:").unwrap(); - write!(debug, "{};{}\n", user, password_hash).unwrap(); + if let Ok(mut debug) = File::open("debug:") { + let _ = write!(debug, "{};{}\n", user, password_hash); } - let mut passwd_string = String::new(); - File::open("file:etc/passwd").unwrap().read_to_string(&mut passwd_string).unwrap(); - - let mut passwd_option = None; for line in passwd_string.lines() { if let Ok(passwd) = Passwd::parse(line) { if user == passwd.user && password_hash == passwd.hash { @@ -118,37 +107,39 @@ pub fn main() { } } } - - if let Some(passwd) = passwd_option { - stdout.write(b"\n").unwrap(); - let _ = stdout.flush(); - - let mut command = Command::new(passwd.shell); - - env::set_current_dir(passwd.home).unwrap(); - - command.env("USER", &user); - command.env("HOME", passwd.home); - command.env("PATH", "file:bin"); - - match command.spawn() { - Ok(mut child) => match child.wait() { - Ok(_status) => (), //println!("login: waited for {}: {:?}", sh, status.code()), - Err(err) => panic!("login: failed to wait for '{}': {}", passwd.shell, err) - }, - Err(err) => panic!("login: failed to execute '{}': {}", passwd.shell, err) - } - - env::set_current_dir("file:").unwrap(); - - stdout.write(b"\x1Bc").unwrap(); - let _ = stdout.flush(); - } else { - stdout.write(b"\nLogin failed\n").unwrap(); - let _ = stdout.flush(); - } } } + + if let Some(passwd) = passwd_option { + if let Ok(mut motd) = File::open("/etc/motd") { + io::copy(&mut motd, &mut stdout).unwrap(); + let _ = stdout.flush(); + } + + let mut command = Command::new(passwd.shell); + + env::set_current_dir(passwd.home).unwrap(); + + command.env("USER", &user); + command.env("HOME", passwd.home); + command.env("PATH", "file:bin"); + + match command.spawn() { + Ok(mut child) => match child.wait() { + Ok(_status) => (), //println!("login: waited for {}: {:?}", sh, status.code()), + Err(err) => panic!("login: failed to wait for '{}': {}", passwd.shell, err) + }, + Err(err) => panic!("login: failed to execute '{}': {}", passwd.shell, err) + } + + break; + } else { + stdout.write(b"\nLogin failed\n").unwrap(); + let _ = stdout.flush(); + } + } else { + stdout.write(b"\n").unwrap(); + let _ = stdout.flush(); } - }); + } }