cleaned up and added install subcommand

main
_ 2025-03-21 13:38:33 -05:00
parent 5aeb4c8d7a
commit 0286d854d6
8 changed files with 155 additions and 42 deletions

40
Cargo.lock generated
View File

@ -2,6 +2,12 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "anyhow"
version = "1.0.97"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
[[package]]
name = "autocfg"
version = "1.1.0"
@ -20,6 +26,21 @@ version = "2.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
[[package]]
name = "camino"
version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3"
[[package]]
name = "cc"
version = "1.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
@ -88,11 +109,14 @@ dependencies = [
name = "lookaround"
version = "0.1.6"
dependencies = [
"anyhow",
"camino",
"configparser",
"directories",
"mac_address",
"nix",
"rand",
"sys-info",
"thiserror",
"tokio",
]
@ -249,6 +273,12 @@ dependencies = [
"redox_syscall",
]
[[package]]
name = "shlex"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "syn"
version = "1.0.82"
@ -260,6 +290,16 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "sys-info"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "thiserror"
version = "1.0.30"

View File

@ -12,11 +12,14 @@ repository = "https://six-five-six-four.com/git/reactor/lookaround"
version = "0.1.6"
[dependencies]
anyhow = "1.0.97"
camino = "1.1.9"
configparser = "3.0.0"
directories = "5.0.0"
mac_address = "1.1.8"
nix = "0.29.0"
rand = "0.8.4"
sys-info = "0.9.1"
thiserror = "1.0.30"
tokio = { version = "1.14.0", features = ["fs", "net", "rt", "time"] }

View File

@ -28,51 +28,38 @@ Make sure Cargo is installed from [RustUp.](https://rustup.rs/)
cargo install lookaround
# Find your config directory
# Prints something like `Using config dir "/home/user/.config/lookaround"`
# e.g. `$HOME/.config/lookaround`
lookaround config
```
Create the files `client.ini` and/or `server.ini` in that directory
(e.g. /home/user/.config/lookaround/server.ini)
Use `$HOME/.config/lookaround/client.ini` as a hosts file if it's more convenient
for your client to be the source of truth for nicknames.
```ini
# Clients can store MAC-nickname pairs in client.ini, like a hosts file.
# This is useful if your servers are short-lived and you want the clients
# to be the source of truth for nicknames.
[nicknames]
11-11-11-11-11-11 = laptop
22-22-22-22-22-22 = desktop
11-11-11-11-11-11 = bob-laptop
22-22-22-22-22-22 = alice-desktop
```
LookAround will use the system's hostname as its server nickname.
If you have a generic hostname like `ubuntu`, override this in `$HOME/.config/lookaround/server.ini`:
```ini
# Long-lived servers can have their nickname configured in server.ini
[server]
nickname = my-computer
nickname = alice-desktop
```
## Auto-Start (Linux)
Put this systemd unit in `~/.config/systemd/user/lookaround.service`:
Run `lookaround install` or `lookaround install $NICKNAME` if you want to set a nickname.
```ini
[Unit]
Description=LookAround
This will create `$HOME/.config/lookaround/server.ini` and `$HOME/.config/systemd/user/lookaround.service`, and start the systemd user service.
[Service]
ExecStart=/home/user/.cargo/bin/lookaround server
Restart=always
[Install]
WantedBy=default.target
```
Then start the service, check that it's running okay, and enable it for
auto-start:
To check that it's running
```bash
systemctl --user start lookaround
systemctl --user status lookaround
systemctl --user enable lookaround
lookaround client
```
## Auto-Start (Windows)

View File

@ -9,6 +9,10 @@ pub fn try_config_dir() -> Option<PathBuf> {
Some(try_project_dir()?.config_local_dir().into())
}
pub fn try_server_config_path() -> Option<PathBuf> {
Some(try_config_dir()?.join("server.ini"))
}
#[derive(Debug, thiserror::Error)]
pub enum AppError {
#[error(transparent)]

View File

@ -1,7 +1,83 @@
use crate::prelude::*;
use anyhow::{Context as _, Result, anyhow, ensure};
use std::{io::Write as _, process::Command};
pub(crate) fn main() -> Result<(), AppError> {
let path = app_common::try_config_dir().unwrap().join("server.ini");
pub(crate) fn main(nickname: Option<&str>) -> Result<()> {
if let Some(nickname) = nickname {
let path = app_common::try_server_config_path().context("can't find config dir")?;
let text = format!(
"[server]
nickname = {nickname}
"
);
write_new(&path, &text).context("Didn't install LookAround server.ini")?;
}
setup_autostart()?;
Ok(())
}
#[cfg(not(target_os = "linux"))]
fn setup_autostart() -> Result<()> {
anyhow::bail!("LookAround autostart is only implemented for systemd + GNU/Linux");
}
#[cfg(target_os = "linux")]
fn setup_autostart() -> Result<()> {
let dirs = directories::BaseDirs::new().context("Could not find home dir")?;
let home = dirs.config_local_dir();
let path = home.join("systemd").join("user").join("lookaround.service");
let exe_path =
Utf8PathBuf::from_path_buf(std::env::current_exe().context("Can't get current_exe")?)
.map_err(|_| anyhow!("current_exe isn't valid UTF-8"))?;
let text = format!(
"[Unit]
Description=LookAround
[Service]
ExecStart={exe_path} server
Restart=always
[Install]
WantedBy=default.target
"
);
write_new(&path, &text).context("Didn't install systemd service unit")?;
ensure!(
Command::new("systemctl")
.args(["--user", "start", "lookaround"])
.status()?
.success(),
"starting service failed"
);
ensure!(
Command::new("systemctl")
.args(["--user", "enable", "lookaround"])
.status()?
.success(),
"enabling service failed"
);
Ok(())
}
fn write_new(path: &Path, content: &str) -> Result<()> {
use std::fs;
fs::create_dir_all(
path.parent()
.context("Impossible, path should always have a parent")?,
)?;
match fs::File::create_new(path) {
Err(err) if err.kind() == std::io::ErrorKind::AlreadyExists => {
eprintln!("File already exists, won't overwrite: `{path:?}`")
}
Err(err) => Err(err)?,
Ok(mut f) => f.write_all(content.as_bytes())?,
}
Ok(())
}

View File

@ -1,3 +1,4 @@
use anyhow::{Result, bail};
use prelude::*;
pub mod app_common;
@ -9,7 +10,7 @@ mod prelude;
mod server;
pub mod tlv;
fn main() -> Result<(), AppError> {
fn main() -> Result<()> {
let rt = tokio::runtime::Builder::new_current_thread()
.enable_io()
.enable_time()
@ -20,7 +21,7 @@ fn main() -> Result<(), AppError> {
Ok(())
}
async fn async_main() -> Result<(), AppError> {
async fn async_main() -> Result<()> {
let mut args = env::args();
let _exe_name = args.next();
@ -32,19 +33,21 @@ async fn async_main() -> Result<(), AppError> {
match subcommand.as_ref() {
"--version" => {
println!("lookaround v{}", env!("CARGO_PKG_VERSION"));
Ok(())
}
"client" => client::client(args).await,
"client" => client::client(args).await?,
"config" => {
config();
Ok(())
}
"find-nick" => client::find_nick(args).await,
"install" => install::main(),
"my-ips" => my_ips(),
"server" => server::server(args).await,
x => Err(CliArgError::UnknownSubcommand(x.to_string()).into()),
"find-nick" => client::find_nick(args).await?,
"install" => {
let nickname = args.next();
install::main(nickname.as_deref())?
}
"my-ips" => my_ips()?,
"server" => server::server(args).await?,
x => bail!("Unknown subcommand `{x}`"),
}
Ok(())
}
fn config() {

View File

@ -3,12 +3,13 @@ pub use std::{
env,
io::{Cursor, Write},
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
path::PathBuf,
path::{Path, PathBuf},
str::FromStr,
sync::Arc,
time::Duration,
};
pub use camino::Utf8PathBuf;
pub use configparser::ini::Ini;
pub use mac_address::{MacAddress, get_mac_address};
pub use rand::RngCore;

View File

@ -42,10 +42,9 @@ pub async fn server<I: Iterator<Item = String>>(args: I) -> Result<(), AppError>
fn configure<I: Iterator<Item = String>>(mut args: I) -> Result<Params, AppError> {
let common = app_common::Params::default();
let mut bind_addrs = vec![];
let mut nickname = String::new();
let mut nickname = sys_info::hostname().unwrap_or_default();
if let Some(dir) = app_common::try_config_dir() {
let path = dir.join("server.ini");
if let Some(path) = app_common::try_server_config_path() {
let mut ini = Ini::new_cs();
if ini.load(&path).is_ok() {
if let Some(x) = ini.get("server", "nickname") {