Skip to content

Instantly share code, notes, and snippets.

@Aplet123
Created June 20, 2020 18:04
Show Gist options
  • Save Aplet123/95fa1aee8742a695034c2146598a3bde to your computer and use it in GitHub Desktop.
Save Aplet123/95fa1aee8742a695034c2146598a3bde to your computer and use it in GitHub Desktop.
It does a good job at executing files.
use std::process::{Command, exit};
use std::env;
use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::fs;
fn stop(msg: &str) -> ! {
println!("Error: {}", msg);
exit(1);
}
fn uwr<T, E>(res: Result<T, E>, msg: &str) -> T {
match res {
Ok(v) => v,
Err(_) => {
stop(msg);
}
}
}
fn uwo<T>(res: Option<T>, msg: &str) -> T {
match res {
Some(v) => v,
None => {
stop(msg);
}
}
}
fn expand(dat: &Vec<&'static str>, vars: HashMap<&str, Vec<String>>) -> Vec<String> {
let mut ret = Vec::new();
for d in dat {
match d.chars().next() {
Some('$') => {
let evaled = uwo(vars.get(&d[1..]), "Invalid variable name.");
for arg in evaled {
ret.push(arg.clone());
}
},
_ => ret.push(d.to_string()),
}
}
ret
}
fn find_path() -> PathBuf {
for i in 0.. {
let path_str = format!("/tmp/execfile{}", i);
let path = Path::new(&path_str);
if !path.exists() {
return path.to_path_buf();
}
}
panic!("This should never happen.");
}
fn gen_comps() -> HashMap<&'static str, Vec<&'static str>> {
let mut ret = HashMap::new();
ret.insert("rust", vec!["rustc", "$FILENAME", "$FLAGS", "-o", "$OUTFILE"]);
ret.insert("c", vec!["gcc", "$FILENAME", "$FLAGS", "-o", "$OUTFILE"]);
ret.insert("cpp", vec!["g++", "$FILENAME", "$FLAGS", "-o", "$OUTFILE"]);
ret.insert("hask", vec!["ghc", "$FILENAME", "$FLAGS", "-o", "$OUTFILE", "-no-keep-hi-files", "-no-keep-o-files"]);
ret
}
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
stop("Not enough arguments were provided.");
}
let name = &args[0][uwo(args[0].find("exec"), "Bad executable name.") + 4..];
let comps = gen_comps();
let comp = uwo(comps.get(name), "Invalid executable name.");
let mut vars: HashMap<&str, Vec<String>> = HashMap::new();
let outfile = uwo(find_path().to_str(), "The path is magically not UTF-8.").to_string();
vars.insert("OUTFILE", vec![outfile.clone()]);
let filename = args[1].clone();
vars.insert("FILENAME", vec![filename.clone()]);
let rest = &args[2..];
let mut flags: Vec<String> = Vec::new();
let mut args: Vec<String> = Vec::new();
let mut is_args = false;
for s in rest {
if !is_args && s == "-:" {
is_args = true;
continue;
}
if is_args {
args.push(s.clone());
} else {
flags.push(s.clone());
}
}
vars.insert("FLAGS", flags);
let fullcmd = expand(comp, vars);
if fullcmd.is_empty() {
stop("Command is empty.");
}
println!("Compiling...");
let mut child = uwr(Command::new(&fullcmd[0])
.args(&fullcmd[1..])
.spawn()
, "Could not spawn command.");
let code = uwr(child.wait(), "Command has already terminated.");
if !code.success() {
stop("Compilation failed.");
}
println!("Running...");
let mut prog = uwr(Command::new(&outfile)
.args(args)
.spawn()
, "Could not spawn command.");
uwr(prog.wait(), "Command has already terminated.");
uwr(fs::remove_file(&outfile), "File has already been removed.");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment