Skip to content

Commit 4033e5b

Browse files
author
etke
committed
Add no-color arg and respect NO_COLOR env var
1 parent 4aef4eb commit 4033e5b

File tree

3 files changed

+70
-24
lines changed

3 files changed

+70
-24
lines changed

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ pub mod pe;
5454
#[cfg(feature = "shared")]
5555
#[macro_use]
5656
pub mod shared;
57+
pub mod output;

src/main.rs

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@ use goblin::mach::Mach;
1212
use goblin::Object;
1313
use ignore::Walk;
1414
use memmap::Mmap;
15-
#[cfg(not(feature = "color"))]
16-
use serde_json::to_string_pretty;
17-
use serde_json::{json, Value};
15+
use serde_json::{json, to_string_pretty, Value};
1816
use sysinfo::{
1917
PidExt, ProcessExt, ProcessRefreshKind, RefreshKind, System, SystemExt,
2018
};
@@ -36,15 +34,20 @@ use binary::{
3634
use checksec::elf;
3735
#[cfg(feature = "macho")]
3836
use checksec::macho;
37+
use checksec::output;
3938
#[cfg(feature = "pe")]
4039
use checksec::pe;
4140
use checksec::underline;
4241

43-
fn json_print(data: &Value, pretty: bool) {
44-
if pretty {
42+
fn json_print(data: &Value, settings: &output::Settings) {
43+
if settings.pretty {
4544
#[cfg(feature = "color")]
46-
if let Ok(colored_json) = to_colored_json_auto(data) {
47-
println!("{}", colored_json);
45+
if settings.color {
46+
if let Ok(colored_json) = to_colored_json_auto(data) {
47+
println!("{}", colored_json);
48+
}
49+
} else if let Ok(json_str) = to_string_pretty(data) {
50+
println!("{}", json_str);
4851
}
4952
#[cfg(not(feature = "color"))]
5053
if let Ok(json_str) = to_string_pretty(data) {
@@ -135,13 +138,13 @@ fn parse(file: &Path) -> Result<Vec<Binary>, Error> {
135138
Err(Error::IO(io::Error::last_os_error()))
136139
}
137140

138-
fn walk(basepath: &Path, json: bool, pretty: bool) {
141+
fn walk(basepath: &Path, settings: &output::Settings) {
139142
let mut bins: Vec<Binary> = Vec::new();
140143
for result in Walk::new(basepath).flatten() {
141144
if let Some(filetype) = result.file_type() {
142145
if filetype.is_file() {
143146
if let Ok(mut result) = parse(result.path()) {
144-
if json {
147+
if settings.json {
145148
bins.append(&mut result);
146149
} else {
147150
for bin in &result {
@@ -152,8 +155,8 @@ fn walk(basepath: &Path, json: bool, pretty: bool) {
152155
}
153156
}
154157
}
155-
if json {
156-
json_print(&json!(Binaries::new(bins)), pretty);
158+
if settings.json {
159+
json_print(&json!(Binaries::new(bins)), settings);
157160
}
158161
}
159162
#[allow(clippy::too_many_lines, clippy::cognitive_complexity)]
@@ -193,6 +196,11 @@ fn main() {
193196
.long("json")
194197
.help("Output in json format"),
195198
)
199+
.arg(
200+
Arg::new("no-color")
201+
.long("no-color")
202+
.help("Disables color output"),
203+
)
196204
.arg(
197205
Arg::new("pretty")
198206
.long("pretty")
@@ -237,14 +245,19 @@ fn main() {
237245
)
238246
.get_matches();
239247

240-
let json = args.is_present("json");
241248
let file = args.value_of("file");
242249
let directory = args.value_of("directory");
243-
let pretty = args.is_present("pretty");
244250
let procids = args.value_of("pid");
245251
let procname = args.value_of("process");
246252
let procall = args.is_present("process-all");
247253

254+
let settings = output::Settings::set(
255+
#[cfg(feature = "color")]
256+
!args.is_present("no-color"),
257+
args.is_present("json"),
258+
args.is_present("pretty"),
259+
);
260+
248261
if procall {
249262
let system = System::new_with_specifics(
250263
RefreshKind::new()
@@ -253,7 +266,7 @@ fn main() {
253266
let mut procs: Vec<Process> = Vec::new();
254267
for (pid, proc_entry) in system.processes() {
255268
if let Ok(results) = parse(proc_entry.exe()) {
256-
if json {
269+
if settings.json {
257270
#[allow(clippy::cast_sign_loss)]
258271
procs.append(&mut vec![Process::new(
259272
pid.as_u32() as usize,
@@ -271,8 +284,8 @@ fn main() {
271284
}
272285
}
273286
}
274-
if json {
275-
json_print(&json!(Processes::new(procs)), pretty);
287+
if settings.json {
288+
json_print(&json!(Processes::new(procs)), &settings);
276289
}
277290
} else if let Some(procids) = procids {
278291
let procids: Vec<sysinfo::Pid> = procids
@@ -310,14 +323,14 @@ fn main() {
310323

311324
match parse(process.exe()) {
312325
Ok(results) => {
313-
if json {
326+
if settings.json {
314327
#[allow(clippy::cast_sign_loss)]
315328
json_print(
316329
&json!(Process::new(
317330
procid.as_u32() as usize,
318331
results
319332
)),
320-
pretty,
333+
&settings,
321334
);
322335
} else {
323336
for result in &results {
@@ -350,7 +363,7 @@ fn main() {
350363
let mut procs: Vec<Process> = Vec::new();
351364
for proc_entry in sysprocs {
352365
if let Ok(results) = parse(proc_entry.exe()) {
353-
if json {
366+
if settings.json {
354367
#[allow(clippy::cast_sign_loss)]
355368
procs.append(&mut vec![Process::new(
356369
proc_entry.pid().as_u32() as usize,
@@ -372,8 +385,8 @@ fn main() {
372385
eprintln!("No process found matching name {}", procname);
373386
process::exit(1);
374387
}
375-
if json {
376-
json_print(&json!(Processes::new(procs)), pretty);
388+
if settings.json {
389+
json_print(&json!(Processes::new(procs)), &settings);
377390
}
378391
} else if let Some(directory) = directory {
379392
let directory_path = Path::new(directory);
@@ -383,7 +396,7 @@ fn main() {
383396
process::exit(1);
384397
}
385398

386-
walk(directory_path, json, pretty);
399+
walk(directory_path, &settings);
387400
} else if let Some(file) = file {
388401
let file_path = Path::new(file);
389402

@@ -394,8 +407,8 @@ fn main() {
394407

395408
match parse(file_path) {
396409
Ok(results) => {
397-
if json {
398-
json_print(&json!(Binaries::new(results)), pretty);
410+
if settings.json {
411+
json_print(&json!(Binaries::new(results)), &settings);
399412
} else {
400413
for result in &results {
401414
println!("{}", result);

src/output.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#[cfg(feature = "color")]
2+
use std::env;
3+
#[cfg(feature = "color")]
4+
use colored::control;
5+
6+
pub struct Settings {
7+
#[cfg(feature = "color")]
8+
pub color: bool,
9+
pub json: bool,
10+
pub pretty: bool,
11+
}
12+
13+
impl Settings {
14+
#[must_use]
15+
#[cfg(feature = "color")]
16+
pub fn set(color: bool, json: bool, pretty: bool) -> Self {
17+
if color {
18+
// honor NO_COLOR if it is set within the environment
19+
if env::var("NO_COLOR").is_ok() {
20+
return Self { color: false, json, pretty };
21+
}
22+
} else {
23+
control::set_override(false);
24+
}
25+
Self { color, json, pretty }
26+
}
27+
#[must_use]
28+
#[cfg(not(feature = "color"))]
29+
pub fn set(json: bool, pretty: bool) -> Self {
30+
Self { json, pretty }
31+
}
32+
}

0 commit comments

Comments
 (0)