Skip to content

Commit

Permalink
default config locations (#18)
Browse files Browse the repository at this point in the history
implement default config locations
  • Loading branch information
Mydayyy authored Sep 18, 2024
1 parent 356fc77 commit 41a8d8a
Show file tree
Hide file tree
Showing 7 changed files with 177 additions and 19 deletions.
56 changes: 53 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description = """
pbcli is a command line client which allows to upload and download
pastes from privatebin directly from the command line.
"""
version = "2.4.0"
version = "2.5.0"
authors = ["Mydayyy"]
edition = "2021"
documentation = "https://github.com/Mydayyy/pbcli"
Expand Down Expand Up @@ -47,3 +47,5 @@ terminal_size = "0.1.17"
parse-size = { version = "1.0.0", features = ["std"] }
uniffi = { version = "0.28.0", optional = true, features = ["cli"] }
openssl = { version = "0.10", features = ["vendored"] }
directories = "5.0.1"
log = "0.4.22"
65 changes: 54 additions & 11 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,63 @@
use std::env;
use std::ffi::OsString;
use std::io::BufRead;
use std::path::{Path, PathBuf};

pub fn get_args() -> Vec<OsString> {
let mut env_args = std::env::args_os();
fn is_valid_config(p: &Path) -> bool {
log::debug!("looking for config at {}", p.display());
p.exists() && p.is_file()
}

fn get_config_path(skip_default_locations: bool) -> Option<OsString> {
// check if config env var is set and use it
if let Some(path) = env::var_os("PBCLI_CONFIG_PATH") {
log::debug!("using config pointed to by PBCLI_CONFIG_PATH");
return Some(path);
};

log::debug!("PBCLI_CONFIG_PATH not set");

if skip_default_locations {
log::debug!("skip_default_locations set. not checking default config locations");
return None;
}

// check user specific config location
let project_dirs = directories::ProjectDirs::from("eu", "mydayyy", env!("CARGO_PKG_NAME"))?;
let user_config_dir = project_dirs.config_local_dir();
let user_config_file = user_config_dir.join("config");
if is_valid_config(&user_config_file) {
return Some(user_config_file.into());
}

// linux only: check /etc/pbcli/config
if cfg!(unix) {
let system_config_file = PathBuf::from("/etc/pbcli/config");
if is_valid_config(&system_config_file) {
return Some(system_config_file.into());
}
}

None
}

let path = match env::var_os("PBCLI_CONFIG_PATH") {
None => return env_args.collect(),
pub fn get_config_args(skip_default_locations: bool) -> Vec<OsString> {
let path = match get_config_path(skip_default_locations) {
None => {
log::debug!("no config found");
return vec![];
}
Some(path) => path,
};

log::debug!("using config {}", path.to_string_lossy());

let handle = match std::fs::File::open(path) {
Ok(file) => file,
Err(_) => return env_args.collect(), // TODO: Raise error
Err(_) => {
log::debug!("failed to open config. using cli args only");
return vec![];
} // TODO: Raise error
};

let reader = std::io::BufReader::new(handle);
Expand All @@ -30,11 +75,9 @@ pub fn get_args() -> Vec<OsString> {
config_args.push(line.into());
});

if let Some(binary_path) = env_args.next() {
config_args.insert(0, binary_path);
}

config_args.extend(env_args);

config_args
}

pub fn get_cli_args() -> Vec<OsString> {
std::env::args_os().collect()
}
11 changes: 11 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use base64::DecodeError;
use data_url::DataUrlError;
use log::SetLoggerError;
use miniz_oxide::inflate::TINFLStatus;
use serde_json::Error;
use std::fmt;
Expand Down Expand Up @@ -35,6 +36,7 @@ pub enum PasteError {
NotAFile,
InvalidTokenType(String),
OidcBadRequest(serde_json::Value),
LoggerInit(log::SetLoggerError),
}

impl std::error::Error for PasteError {}
Expand Down Expand Up @@ -71,6 +73,9 @@ impl fmt::Display for PasteError {
write!(f, "Invalid token type: {}", token_type)
}
PasteError::OidcBadRequest(json) => write!(f, "{}", json),
PasteError::LoggerInit(err) => {
write!(f, "Failed to init logger: {}", err)
}
}
}
}
Expand Down Expand Up @@ -128,3 +133,9 @@ impl From<DataUrlError> for PasteError {
PasteError::InvalidAttachment(err)
}
}

impl From<SetLoggerError> for PasteError {
fn from(err: SetLoggerError) -> Self {
PasteError::LoggerInit(err)
}
}
24 changes: 24 additions & 0 deletions src/logger.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use log::{Metadata, Record};

pub(crate) struct SimpleLogger(());
const LOGGER: &SimpleLogger = &SimpleLogger(());

impl SimpleLogger {
pub(crate) fn init() -> Result<(), log::SetLoggerError> {
log::set_logger(LOGGER)
}
}

impl log::Log for SimpleLogger {
fn enabled(&self, _metadata: &Metadata) -> bool {
true
}

fn log(&self, record: &Record) {
if self.enabled(record.metadata()) {
eprintln!("{} {}: {}", record.level(), record.target(), record.args());
}
}

fn flush(&self) {}
}
20 changes: 18 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ use pbcli::opts::Opts;
use pbcli::privatebin::{DecryptedComment, DecryptedCommentsMap, DecryptedPaste};
use pbcli::util::check_filesize;
use serde_json::Value;
use std::ffi::OsString;
use std::io::IsTerminal;
use std::io::{Read, Write};

mod logger;

fn get_stdin() -> std::io::Result<String> {
if std::io::stdin().is_terminal() {
return Ok("".into());
Expand Down Expand Up @@ -169,8 +172,21 @@ fn handle_comment(opts: &Opts) -> PbResult<()> {
}

fn main() -> PbResult<()> {
let args = pbcli::config::get_args();
let opts: Opts = Opts::parse_from(args);
crate::logger::SimpleLogger::init()?;

let mut env_args = pbcli::config::get_cli_args();
let mut opts: Opts = Opts::parse_from(&env_args);

if opts.debug {
log::set_max_level(log::LevelFilter::Debug);
}

let config_args = pbcli::config::get_config_args(opts.no_default_config);
let mut merged_args: Vec<OsString> = vec![];
merged_args.extend(env_args.drain(0..1));
merged_args.extend(config_args);
merged_args.extend(env_args);
opts.update_from(merged_args);

let url_has_query = opts.get_url().query().is_some();
if url_has_query {
Expand Down
16 changes: 14 additions & 2 deletions src/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ Project home page: https://github.com/Mydayyy/pbcli";

#[derive(Debug, Parser, Clone)]
#[cfg_attr(feature = "uniffi", derive(uniffi::Record))]
#[clap(setting = clap::AppSettings::AllArgsOverrideSelf, version = env ! ("CARGO_PKG_VERSION"), author = "Mydayyy <[email protected]>", about = ABOUT)]
#[clap(term_width(if let Some((terminal_size::Width(w), _)) = terminal_size::terminal_size() { w as usize } else { 120 }))]
#[clap(setting = clap::AppSettings::AllArgsOverrideSelf, version = env ! ("CARGO_PKG_VERSION"), author = "Mydayyy <[email protected]>", about = ABOUT
)]
#[clap(term_width(if let Some((terminal_size::Width(w), _)) = terminal_size::terminal_size() { w as usize } else { 120 }
))]
#[clap(rename_all = "kebab-case")]
pub struct Opts {
#[clap(required_unless_present("host"), parse(try_from_str))]
Expand Down Expand Up @@ -95,6 +97,16 @@ pub struct Opts {
#[clap(long)]
#[clap(help("password to send to the token endpoint"))]
pub oidc_password: Option<String>,

#[cfg_attr(feature = "uniffi", uniffi(default = false))]
#[clap(long)]
#[clap(help("print debug output to stderr"))]
pub debug: bool,

#[cfg_attr(feature = "uniffi", uniffi(default = false))]
#[clap(long)]
#[clap(help("do not look for config in default locations"))]
pub no_default_config: bool,
}

impl Opts {
Expand Down

0 comments on commit 41a8d8a

Please sign in to comment.