#[cfg(not(unix))]
compile_error!("YOM is available on UNIX-like systems only.");
use std::io;
use std::fs::File;
use std::io::{BufRead, BufReader};
mod builtins; mod externals; mod internals; use internals::helpers::*; use std::process::exit;
fn main() {
let mut args = std::env::args_os();
args.next();
let path = match args.next() {
Some(p) => p,
None => return,
};
let f = File::open(&path).expect("Expected file");
let mut reader = BufReader::new(f);
let mut line = String::new();
let stdout = io::stdout();
let mut lock = stdout.lock();
while reader.read_line(&mut line).unwrap() > 0 {
line = line.trim_start().to_string();
if line.starts_with("#") || line == "\n" || line == "" {
line.clear();
continue;
} else if line == "then\n" || line == "then" {
line.clear();
continue;
} else if line == "fi\n" || line == "fi" {
line.clear();
continue;
} else if line.starts_with("/") || line.starts_with("$") {
if line.ends_with(" &\n") {
externals::entry::background(line.strip_suffix(" &\n").unwrap()); line.clear();
continue;
} else if line.ends_with(" &") {
externals::entry::background(line.strip_suffix(" &").unwrap());
line.clear();
continue;
} else {
externals::entry::waitfor(line.as_str()); line.clear();
continue;
}
} else if line.starts_with('e') {
if line.starts_with("exec ") {
externals::entry::exec(line.as_str()); line.clear();
continue;
} else if line.starts_with("echo ") {
let str = line.strip_prefix("echo ").unwrap(); let str = str.strip_suffix("\n").unwrap_or(str); if str.starts_with('"') && str.ends_with('"') {
let str = str.strip_prefix('"').unwrap();
let str = str.strip_suffix('"').unwrap();
builtins::echo::echo(str, &mut lock); line.clear();
continue;
} else {
builtins::echo::echo(str, &mut lock); line.clear();
continue;
}
} else if line.starts_with ("export ") {
let tmp = line.strip_prefix("export ").unwrap();
if let Some((name, data)) = tmp.split_once('=') {
unsafe {
let data = data.strip_suffix("\n").unwrap_or(data);
std::env::set_var(name, data);
}
}
line.clear();
continue;
}
} else if line.starts_with("cd ") {
let dir = line.strip_prefix("cd ").unwrap(); let dir = dir.strip_suffix("\n").unwrap_or(dir); if dir.starts_with('"') && dir.ends_with('"') {
let dir = dir.strip_prefix('"').unwrap(); let dir = dir.strip_suffix('"').unwrap(); let _ = builtins::cd::cd(dir); line.clear();
continue;
} else {
let _ = builtins::cd::cd(dir); line.clear();
continue;
}
} else if line == "pwd\n" {
let _ = builtins::pwd::pwd(&mut lock); line.clear();
continue;
} else if line.starts_with("read") {
let prompt = line.strip_prefix("read ").unwrap(); let prompt = prompt.strip_suffix("\n").unwrap_or(prompt); if prompt.starts_with('"') && prompt.ends_with('"') {
let prompt = prompt.strip_prefix('"').unwrap(); let prompt = prompt.strip_suffix('"').unwrap(); let val = builtins::read::read(prompt); unsafe {
std::env::set_var(prompt, val);
}
line.clear();
continue;
} else {
let val = builtins::read::read(prompt); unsafe {
std::env::set_var(prompt, val);
}
line.clear();
continue;
}
} else if line == "exit\n" {
builtins::exit::exit(0); line.clear();
continue;
} else if line.starts_with("exit ") {
let code = line.strip_prefix("exit ").unwrap();
let code: i32 = code.strip_suffix("\n").unwrap_or(code).parse().unwrap_or(1); builtins::exit::exit(code); line.clear();
continue;
} else if line.starts_with("if ") {
let split = shell_words::split(&line).unwrap();
let left: &str = &split[2];
let operator: &str = &split[3];
let right: &str = &split[4];
if left.starts_with("$") || right.starts_with("$") {
let tmp = left.strip_prefix("$").unwrap_or(left);
let left = std::env::var_os(tmp).unwrap_or(tmp.into());
let left = left.to_str().expect("Not valid UTF-8");
let tmp = right.strip_prefix("$").unwrap_or(right);
let right = std::env::var_os(tmp).unwrap_or(tmp.into());
let right = right.to_str().expect("Not valid UTF-8");
let val = str_or_int(left, right);
if val == true {
let left: i64 = left.parse().unwrap();
let right: i64 = right.parse().unwrap();
let val = ncmp(left, right, operator);
if val == true {
line.clear();
continue;
} else {
line.clear();
while reader.read_line(&mut line).unwrap() > 0 {
let trimmed = line.strip_prefix("\n").unwrap_or(&line);
if trimmed == "fi" {
line.clear();
break;
}
line.clear();
}
}
} else {
let val = strcmp(left, right, operator);
if val == true {
line.clear();
continue;
} else {
line.clear();
while reader.read_line(&mut line).unwrap() > 0 {
let trimmed = line.strip_prefix("\n").unwrap_or(&line);
if trimmed == "fi" {
line.clear();
break;
}
line.clear();
}
}
}
} else {
let val = str_or_int(left, right);
if val == true {
let left: i64 = left.parse().unwrap();
let right: i64 = right.parse().unwrap();
let val = ncmp(left, right, operator);
if val == true {
line.clear();
continue;
} else {
line.clear();
while reader.read_line(&mut line).unwrap() > 0 {
let trimmed = line.strip_prefix("\n").unwrap_or(&line);
if trimmed == "fi" {
line.clear();
break;
}
line.clear();
}
}
} else {
let val = strcmp(left, right, operator);
if val == true {
line.clear();
continue;
} else {
line.clear();
while reader.read_line(&mut line).unwrap() > 0 {
let trimmed = line.strip_prefix("\n").unwrap_or(&line);
if trimmed == "fi" {
line.clear();
break;
}
line.clear();
}
}
}
}
line.clear();
continue;
} else {
exit(1);
}
}
exit(0);
}