# floss-cli ????
??????**???? API/??**?????? Rust ??? FLOSS CLI ????
## 1. ??
```toml
[dependencies]
floss-cli = "0.1.1"
```
> ???? tokio ???????????????? tokio runtime ??
## 2. ????
- ?????????? FLOSS CLI?`floss`/`floss.exe`????? `python -m floss`?
- ????? **CLI**???? FLOSS ? Python API?
## 3. ?? FlossCli????
### 3.1 ????????
```rust
use floss_cli::{FlossCli, Result};
#[tokio::main]
async fn main() -> Result<()> {
let cli = FlossCli::detect().await?;
Ok(())
}
```
### 3.2 ????
```rust
use floss_cli::{FlossCli, Result};
#[tokio::main]
async fn main() -> Result<()> {
let cli = FlossCli::new("floss");
let cli = FlossCli::python_module("python"); // python -m floss
Ok(())
}
```
### 3.3 ???????????????
1. `FLOSS_EXE`????????????
2. `FLOSS_PYTHON` + `FLOSS_PYTHON_ARGS`??? Python ????????
3. `PATH` ?? `floss`/`floss.exe`
4. ?? Python ???Windows?`python/python3/py -3`????`python3/python`?
`FLOSS_PYTHON_ARGS` ???
- ?????
- ?? `'` ? `"` ?????????
- ??? `"` ????????????????
## 4. ???????FlossCommand?
```rust
use floss_cli::{FlossCli, Result};
#[tokio::main]
async fn main() -> Result<()> {
let cli = FlossCli::detect().await?;
let cmd = cli
.command()
.arg("--only")
.args(["static", "decoded"])
.sample("malware.exe");
let line = cmd.command_line();
println!("{}", line); // program + args
Ok(())
}
```
- `.arg(...)` / `.args(...)`???????
- `.sample(...)`????? `--`????????????
- `.command_line()`??? `program + args`?????/??
## 5. ??????????
### 5.1 ????
- `run().await`??? stdout/stderr???????? 0 ?????
- `run_allow_exit_codes([1, 2]).await`????????????
- `run_raw().await`??? stdout/stderr???????
- `run_raw_limited(max_bytes).await`??? stdout/stderr ?????
### 5.2 JSON ??
- `run_json::<T>().await`???? `-j/--json`???????????? `T`
- `run_results().await`?????? `ResultDocument`
### 5.3 ?????????????
- `run_inherit().await`?stdout/stderr ???????????
- `run_inherit_checked().await`??????? 0 ?????
### 5.4 ?????
- `spawn()`?stdout/stderr ??????? `tokio::process::Child`
- `spawn_piped()`?stdout/stderr ? piped??? `Child`
> `spawn/spawn_piped` ?????????? Job Object?????????????
## 6. ???????
### 6.1 FlossOutput
`run/run_raw/run_allow_exit_codes` ?? `FlossOutput`?
- `program` / `args` / `status`
- `stdout: Vec<u8>` / `stderr: Vec<u8>`
????????
- `stdout_lossy()` / `stderr_lossy()`??? UTF-8
- `stdout_string()` / `stderr_string()`??? UTF-8
### 6.2 FlossOutputLimited
`run_raw_limited` ?? `FlossOutputLimited`????
- `stdout_truncated` / `stderr_truncated` ????
### 6.3 JSON ????
?????`ResultDocument`??? `floss_cli::results`??
- `decoding_function_scores` ? key ?????? `0x` ?????????
## 7. ????????
- `FlossCli::with_timeout(...)` ? `FlossCommand::with_timeout(...)` ????
- ????????????Best-effort??
- Windows??? Job Object?`KILL_ON_JOB_CLOSE`?????? `taskkill`/`kill`
- Unix?? `SIGTERM`??? 100ms????? `SIGKILL`
- ??????? `FlossError::TimedOutKillFailed`
## 8. ??????
### 8.1 ?? JSON ??
```rust
use floss_cli::{FlossCli, Result, ResultDocument};
#[tokio::main]
async fn main() -> Result<()> {
let cli = FlossCli::detect().await?;
let doc: ResultDocument = cli
.command()
.sample("malware.exe")
.run_results()
.await?;
println!("decoded strings: {}", doc.strings.decoded_strings.len());
Ok(())
}
```
### 8.2 ??? 0 ???
```rust
use floss_cli::{FlossCli, Result};
#[tokio::main]
async fn main() -> Result<()> {
let cli = FlossCli::detect().await?;
let out = cli.command().sample("malware.exe").run_allow_exit_codes([1]).await?;
println!("status: {}", out.status);
Ok(())
}
```
### 8.3 ???????????
```rust
use floss_cli::{FlossCli, Result};
#[tokio::main]
async fn main() -> Result<()> {
let cli = FlossCli::detect().await?;
cli.command().arg("-H").run_inherit().await?;
Ok(())
}
```
### 8.4 ??????????
```rust
use floss_cli::{FlossCli, Result};
#[tokio::main]
async fn main() -> Result<()> {
let cli = FlossCli::detect().await?;
let out = cli.command().sample("malware.exe").run_raw_limited(1024 * 1024).await?;
println!("stdout truncated: {}", out.stdout_truncated);
Ok(())
}
```
### 8.5 spawn_piped + ????
```rust
use floss_cli::{FlossCli, Result};
use tokio::io::AsyncReadExt;
#[tokio::main]
async fn main() -> Result<()> {
let cli = FlossCli::detect().await?;
let mut child = cli.command().sample("malware.exe").spawn_piped()?;
let mut stdout = Vec::new();
if let Some(mut reader) = child.stdout.take() {
reader.read_to_end(&mut stdout).await?;
}
let status = child.wait().await?;
println!("status: {}", status);
Ok(())
}
```
## 9. ?????????
`FlossError` ?????
- `AutoDetectFailed`???????
- `Io`?????/IO ??
- `Json`?JSON ??????
- `NonZeroExit`?? 0 ?????? stdout/stderr?
- `TimedOut` / `TimedOutKillFailed`????????
- `Utf8`??? UTF-8 ????
`NonZeroExit`/`TimedOut` ??? `command`?program + args?????????????
## 10. ?????
- Windows??? Job Object ?????????? `taskkill`/`kill`
- Unix??? `SIGTERM` ? `SIGKILL`
- `spawn/spawn_piped` ???????????