From 00e90e7e7d3bdc2e35fea0fab2dc704326831bad Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Fri, 29 Oct 2021 01:29:56 -0400 Subject: support command line arguments in EDITOR/VISUAL --- src/edit.rs | 72 ++++++++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 25 deletions(-) (limited to 'src/edit.rs') diff --git a/src/edit.rs b/src/edit.rs index a62dffa..1a831a7 100644 --- a/src/edit.rs +++ b/src/edit.rs @@ -8,27 +8,6 @@ pub fn edit(contents: &str, help: &str) -> Result { var = "EDITOR"; std::env::var_os(var).unwrap_or_else(|| "/usr/bin/vim".into()) }); - let editor = std::path::Path::new(&editor); - - let mut args = vec![]; - match editor.file_name() { - Some(editor) => match editor.to_str() { - Some("vim" | "nvim") => { - // disable swap files and viminfo for password entry - args.push(std::ffi::OsStr::new("-ni")); - args.push(std::ffi::OsStr::new("NONE")); - } - _ => { - // other editor support welcomed - } - }, - None => { - return Err(Error::InvalidEditor { - var: var.to_string(), - editor: editor.as_os_str().to_os_string(), - }) - } - } let dir = tempfile::tempdir().unwrap(); let file = dir.path().join("rbw"); @@ -37,20 +16,56 @@ pub fn edit(contents: &str, help: &str) -> Result { fh.write_all(help.as_bytes()).unwrap(); drop(fh); - args.push(file.as_os_str()); - let res = std::process::Command::new(&editor).args(&args).status(); + let (cmd, args) = if contains_shell_metacharacters(&editor) { + let mut cmdline = std::ffi::OsString::new(); + cmdline.extend([ + editor.as_ref(), + std::ffi::OsStr::new(" "), + file.as_os_str(), + ]); + + let editor_args = vec![std::ffi::OsString::from("-c"), cmdline]; + (std::path::Path::new("/bin/sh"), editor_args) + } else { + let editor = std::path::Path::new(&editor); + let mut editor_args = vec![]; + + match editor.file_name() { + Some(editor) => match editor.to_str() { + Some("vim" | "nvim") => { + // disable swap files and viminfo for password entry + editor_args.push(std::ffi::OsString::from("-ni")); + editor_args.push(std::ffi::OsString::from("NONE")); + } + _ => { + // other editor support welcomed + } + }, + None => { + return Err(Error::InvalidEditor { + var: var.to_string(), + editor: editor.as_os_str().to_os_string(), + }) + } + } + editor_args.push(file.clone().into_os_string()); + (editor, editor_args) + }; + + let res = std::process::Command::new(&cmd).args(&args).status(); match res { Ok(res) => { if !res.success() { return Err(Error::FailedToRunEditor { - editor: editor.to_owned(), + editor: cmd.to_owned(), + args, res, }); } } Err(err) => { return Err(Error::FailedToFindEditor { - editor: editor.to_owned(), + editor: cmd.to_owned(), err, }) } @@ -63,3 +78,10 @@ pub fn edit(contents: &str, help: &str) -> Result { Ok(contents) } + +fn contains_shell_metacharacters(cmd: &std::ffi::OsStr) -> bool { + match cmd.to_str() { + Some(s) => s.contains(&[' ', '$', '\'', '"'][..]), + None => false, + } +} -- cgit v1.2.3-54-g00ecf