Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::collections::{BTreeMap, HashMap, HashSet};
use std::fs;
use std::path::{Path, PathBuf};

use anyhow::{bail, Context, Result};
use anyhow::{Context, Result, bail};
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Deserialize, Serialize)]
Expand Down
37 changes: 26 additions & 11 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::path::Path;
use std::process::Command;
use std::time::Duration;

use anyhow::{bail, Context, Result};
use anyhow::{Context, Result, bail};
use cli::{Commands, ConfigCommands};
use config::{Config, ServiceConfig};
use scan::model::{JoinedPortRecord, ScanRecord};
Expand All @@ -26,7 +26,7 @@ pub fn execute(cli: cli::Cli) -> Result<()> {
render::json::print_pretty(&records)?;
}
Commands::List => {
let cfg = Config::load(&config_path)?;
let cfg = load_config_or_empty(&config_path)?;
let joined = join_records(&scan::scan_listeners()?, &cfg);
if cli.json {
render::json::print_pretty(&joined)?;
Expand All @@ -35,7 +35,7 @@ pub fn execute(cli: cli::Cli) -> Result<()> {
}
}
Commands::Tui => {
let cfg = Config::load(&config_path)?;
let cfg = load_config_or_empty(&config_path)?;
tui::run_tui(config_path.as_path(), cfg)?;
}
Commands::Kill {
Expand All @@ -58,7 +58,7 @@ pub fn execute(cli: cli::Cli) -> Result<()> {
start_service(svc)?;
}
Commands::Doctor => {
let cfg = Config::load(&config_path)?;
let cfg = load_config_or_empty(&config_path)?;
let report = config::doctor::doctor(&cfg, &scan::scan_listeners()?);
if cli.json {
render::json::print_pretty(&report)?;
Expand All @@ -70,14 +70,20 @@ pub fn execute(cli: cli::Cli) -> Result<()> {
}
}
Commands::Urls { host } => {
let cfg = Config::load(&config_path)?;
let cfg = load_config_or_empty(&config_path)?;
let records = scan::scan_listeners()?;

let hostname = host.unwrap_or_else(|| {
hostname::get()
let name = hostname::get()
.unwrap_or_default()
.to_string_lossy()
.to_string()
.to_string();

if name.ends_with(".local") {
name
} else {
format!("{name}.local")
}
});

let mut services = cfg.services.iter().collect::<Vec<_>>();
Expand Down Expand Up @@ -148,14 +154,23 @@ fn start_service(service: &ServiceConfig) -> Result<()> {

let mut cmd = Command::new("zsh");
cmd.arg("-lc").arg(start).current_dir(&service.repo);
let status = cmd.status().context("failed to execute start command")?;
if !status.success() {
bail!("start command exited with {status}");
}
cmd.spawn().context("failed to start service")?;

println!("started {}", service.repo.display());

Ok(())
}

fn load_config_or_empty(path: &Path) -> Result<Config> {
if path.exists() {
Config::load(path)
} else {
Ok(Config {
services: Default::default(),
})
}
}

pub fn open_config(path: &Path) -> Result<()> {
let status = if cfg!(target_os = "macos") {
Command::new("open").arg(path).status()
Expand Down
5 changes: 4 additions & 1 deletion src/proc/kill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ fn signal_group(pgid: i32, hard: bool) -> Result<()> {

fn signal_pid(pid: i32, hard: bool) -> Result<()> {
let sig = if hard { "-KILL" } else { "-TERM" };
let _ = Command::new("kill").arg(sig).arg(pid.to_string()).status()?;
let _ = Command::new("kill")
.arg(sig)
.arg(pid.to_string())
.status()?;
Ok(())
}
6 changes: 1 addition & 5 deletions src/scan/lsof.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@ use anyhow::Result;
use super::model::ListenerRecord;

pub fn parse_lsof_listeners(input: &str) -> Vec<ListenerRecord> {
input
.lines()
.skip(1)
.filter_map(parse_line)
.collect()
input.lines().skip(1).filter_map(parse_line).collect()
}

fn parse_line(line: &str) -> Option<ListenerRecord> {
Expand Down
4 changes: 3 additions & 1 deletion src/scan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ pub fn scan_listeners() -> Result<Vec<ScanRecord>> {
pid: listener.pid,
ppid: ps.as_ref().map(|v| v.ppid),
pgid: ps.as_ref().map(|v| v.pgid),
command: ps.map(|v| v.command).unwrap_or_else(|| "<unknown>".to_string()),
command: ps
.map(|v| v.command)
.unwrap_or_else(|| "<unknown>".to_string()),
cwd,
repo_root,
});
Expand Down
4 changes: 1 addition & 3 deletions src/scan/ss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ use anyhow::Result;
use super::model::ListenerRecord;

pub fn run_ss() -> Result<Vec<ListenerRecord>> {
let out = std::process::Command::new("ss")
.args(["-lptn"])
.output()?;
let out = std::process::Command::new("ss").args(["-lptn"]).output()?;

if !out.status.success() {
return Ok(vec![]);
Expand Down
9 changes: 7 additions & 2 deletions src/tui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,18 @@ pub fn run_tui(config_path: &Path, cfg: Config) -> Result<()> {
Action::Rescan => app.set_rows(join_with_config(&cfg)?),
Action::Term => {
if let Some(row) = app.selected() {
let _ = proc::kill::kill_record(&row.record, Duration::from_millis(1500), false);
let _ = proc::kill::kill_record(
&row.record,
Duration::from_millis(1500),
false,
);
app.set_rows(join_with_config(&cfg)?);
}
}
Action::Kill => {
if let Some(row) = app.selected() {
let _ = proc::kill::kill_record(&row.record, Duration::from_millis(1), true);
let _ =
proc::kill::kill_record(&row.record, Duration::from_millis(1), true);
app.set_rows(join_with_config(&cfg)?);
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/tui/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ pub fn draw(frame: &mut Frame<'_>, app: &App) {

frame.render_widget(table, chunks[0]);

let help = Paragraph::new("k term | K kill | s start | r rescan | e open config | / filter | q quit")
.block(Block::default().borders(Borders::ALL));
let help =
Paragraph::new("k term | K kill | s start | r rescan | e open config | / filter | q quit")
.block(Block::default().borders(Borders::ALL));
frame.render_widget(help, chunks[1]);

let filter = Paragraph::new(format!("filter: {}", app.filter));
Expand Down