Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
If the AppSettings::Multicall setting is given then argv0 is parsed as the first subcommand argument or parsed as normal with any other name.
- Loading branch information
1 parent
236cf58
commit d181174
Showing
6 changed files
with
345 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
use std::{ | ||
env::args_os, | ||
fs::{hard_link, read_link}, | ||
path::{Path, PathBuf}, | ||
process::exit, | ||
}; | ||
|
||
use clap::{Clap, IntoApp}; | ||
|
||
#[derive(Clap, Debug)] | ||
enum Applets { | ||
True, | ||
False, | ||
Install { | ||
#[clap(default_value = "/usr/local/bin")] | ||
path: PathBuf, | ||
}, | ||
} | ||
|
||
#[derive(Clap, Debug)] | ||
#[clap(setting = clap::AppSettings::Multicall)] | ||
struct Args { | ||
#[clap(subcommand)] | ||
applet: Applets, | ||
} | ||
|
||
fn main() { | ||
match Args::parse().applet { | ||
Applets::True => exit(0), | ||
Applets::False => exit(1), | ||
Applets::Install { path } => { | ||
let app = Args::into_app(); | ||
let applets: Vec<_> = app.get_subcommands().map(|c| c.get_name()).collect(); | ||
let exec_path = read_link("/proc/self/exe") | ||
.ok() | ||
.or_else(|| { | ||
args_os().next().and_then(|s| { | ||
let p: &Path = s.as_ref(); | ||
if p.is_absolute() { | ||
Some(PathBuf::from(s)) | ||
} else { | ||
None | ||
} | ||
}) | ||
}) | ||
.expect( | ||
"Should be able to read /proc/self/exe or argv0 should be present and absolute", | ||
); | ||
let mut dest = PathBuf::from(path); | ||
for applet in applets { | ||
if applet == "install" { | ||
continue; | ||
} | ||
dest.push(applet); | ||
hard_link(&exec_path, &dest).expect("Should be able to hardlink"); | ||
dest.pop(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
use std::{ | ||
env::args_os, | ||
fs::{hard_link, read_link}, | ||
path::{Path, PathBuf}, | ||
process::exit, | ||
}; | ||
|
||
use clap::{App, AppSettings, Arg}; | ||
|
||
fn main() { | ||
let app = App::new("busybox") | ||
.setting(AppSettings::ArgRequiredElseHelp) | ||
.setting(AppSettings::Multicall) | ||
.arg( | ||
Arg::new("install") | ||
.long("install") | ||
.about("Install hardlinks for all subcommands in path") | ||
.exclusive(true) | ||
.takes_value(true) | ||
.default_missing_value("/usr/local/bin") | ||
.use_delimiter(false), | ||
) | ||
.subcommand(App::new("true").about("does nothing successfully")) | ||
.subcommand(App::new("false").about("does nothing unsuccessfully")); | ||
let applets: Vec<String> = app | ||
.get_subcommands() | ||
.map(|c| c.get_name().to_owned()) | ||
.collect(); | ||
let matches = app.get_matches(); | ||
if matches.occurrences_of("install") > 0 { | ||
let exec_path = read_link("/proc/self/exe") | ||
.ok() | ||
.or_else(|| { | ||
args_os().next().and_then(|s| { | ||
let p: &Path = s.as_ref(); | ||
if p.is_absolute() { | ||
Some(PathBuf::from(s)) | ||
} else { | ||
None | ||
} | ||
}) | ||
}) | ||
.expect( | ||
"Should be able to read /proc/self/exe or argv0 should be present and absolute", | ||
); | ||
let mut dest = PathBuf::from(matches.value_of("install").unwrap()); | ||
for applet in applets { | ||
dest.push(applet); | ||
hard_link(&exec_path, &dest).expect("Should be able to hardlink"); | ||
dest.pop(); | ||
} | ||
exit(0); | ||
} | ||
|
||
exit(match matches.subcommand_name() { | ||
Some("true") => 0, | ||
Some("false") => 1, | ||
_ => 127, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
use std::process::exit; | ||
|
||
use clap::{App, AppSettings}; | ||
|
||
fn main() { | ||
let matches = App::new("hostname") | ||
.setting(AppSettings::Multicall) | ||
.subcommand(App::new("hostname").about("show hostname")) | ||
.subcommand(App::new("dnsdomainname").about("show domain")) | ||
.get_matches(); | ||
|
||
// If hardlinked as a different name | ||
match matches.subcommand_name() { | ||
Some("hostname") => println!("www"), | ||
Some("dnsdomainname") => println!("example.com"), | ||
_ => exit(127), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.