#[macro_use]
extern crate log;
extern crate env_logger;
extern crate dotenv;
extern crate libc;
use std::{env, ptr, process};
use std::ffi::CString;
use libc::c_char;
use dotenv::{dotenv, DotenvError};
fn make_argv(prog: &CString, args: &[CString])
-> *const *const libc::c_char
{
let mut ptrs: Vec<*const libc::c_char> = Vec::with_capacity(args.len()+1);
ptrs.push(prog.as_ptr());
ptrs.extend(args.iter().map(|tmp| {
tmp.as_ptr()
}));
ptrs.push(ptr::null());
ptrs.as_ptr()
}
fn exec(prog: &str, args: &[String]) -> ! {
let prog = CString::new(prog).expect("Convertable to CString");
let args = args.iter()
.map(|tmp| CString::new(&tmp[..]).expect("Convertable to CString"))
.collect::<Vec<_>>();
let argv = make_argv(&prog, &args);
unsafe {
let exit_code = libc::execvp(*argv, argv);
process::exit(exit_code);
}
}
fn main() {
env_logger::init().expect("Setup env_logger failed");
info!("Loading dotenv");
match dotenv() {
Ok(()) => {},
Err(DotenvError::Io) => {
warn!("No dotenv file found. Skipping.");
},
Err(e) => {
error!("Can't initialize dotenv.");
error!("Error: {:?}", e);
process::exit(1);
}
}
let shell = env::var("SHELL").unwrap_or("/bin/sh".into());
let args = env::args().skip(1).collect::<Vec<String>>();
info!("args: {:?}", args);
match args.len() {
0 => {
info!("Starting '{}' as shell", shell);
exec(&shell, &[]);
},
_ => {
let program = &args[0];
info!("Starting '{}' with arguments: {:?}", program, &args[1..]);
exec(program, &args[1..]);
}
}
}