aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/agent.rs
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2020-04-07 00:15:40 -0400
committerJesse Luehrs <doy@tozt.net>2020-04-07 00:15:40 -0400
commit0f13f2c6d11934bbaceca4dac4c3ba428aae72b7 (patch)
tree167026cd6eec33d2e752edfefa023ecd11072998 /src/bin/agent.rs
parent95da8880e311d4932fd50febab6ef093e5915051 (diff)
downloadrbw-0f13f2c6d11934bbaceca4dac4c3ba428aae72b7.tar.gz
rbw-0f13f2c6d11934bbaceca4dac4c3ba428aae72b7.zip
make the command line tool automatically spawn the agent
Diffstat (limited to 'src/bin/agent.rs')
-rw-r--r--src/bin/agent.rs83
1 files changed, 51 insertions, 32 deletions
diff --git a/src/bin/agent.rs b/src/bin/agent.rs
index 50b13a1..f21abcc 100644
--- a/src/bin/agent.rs
+++ b/src/bin/agent.rs
@@ -1,35 +1,15 @@
-use fs2::FileExt as _;
-use std::io::Write as _;
use tokio::io::AsyncBufReadExt as _;
use tokio::stream::StreamExt as _;
-fn make_pidfile() -> std::fs::File {
+fn make_socket() -> anyhow::Result<tokio::net::UnixListener> {
let runtime_dir = rbw::dirs::runtime_dir();
- std::fs::create_dir_all(&runtime_dir).unwrap();
-
- let mut fh = std::fs::OpenOptions::new()
- .write(true)
- .create(true)
- .open(runtime_dir.join("pidfile"))
- .unwrap();
-
- fh.try_lock_exclusive().unwrap();
-
- fh.set_len(0).unwrap();
- fh.write_all(format!("{}", std::process::id()).as_bytes())
- .unwrap();
-
- fh
-}
-
-fn make_socket() -> tokio::net::UnixListener {
- let runtime_dir = rbw::dirs::runtime_dir();
- std::fs::create_dir_all(&runtime_dir).unwrap();
+ std::fs::create_dir_all(&runtime_dir)?;
let path = runtime_dir.join("socket");
- std::fs::remove_file(&path).unwrap();
-
- tokio::net::UnixListener::bind(path).unwrap()
+ std::fs::remove_file(&path)?;
+ let sock = tokio::net::UnixListener::bind(&path)?;
+ log::debug!("listening on socket {}", path.to_string_lossy());
+ Ok(sock)
}
async fn ensure_login(state: std::sync::Arc<tokio::sync::RwLock<State>>) {
@@ -181,10 +161,49 @@ impl Agent {
}
}
-#[tokio::main]
-async fn main() {
- let _lock = make_pidfile();
- let listener = make_socket();
- let mut agent = Agent::new();
- agent.run(listener).await;
+fn main() {
+ env_logger::from_env(
+ env_logger::Env::default().default_filter_or("info"),
+ )
+ .init();
+
+ let runtime_dir = rbw::dirs::runtime_dir();
+ std::fs::create_dir_all(&runtime_dir).unwrap();
+
+ let (r, w) = nix::unistd::pipe().unwrap();
+ let res = daemonize::Daemonize::new()
+ .pid_file(runtime_dir.join("pidfile"))
+ .exit_action(move || {
+ nix::unistd::close(w).unwrap();
+ let mut buf = [0; 1];
+ nix::unistd::read(r, &mut buf).unwrap();
+ nix::unistd::close(r).unwrap();
+ })
+ .start();
+ nix::unistd::close(r).unwrap();
+
+ match res {
+ Ok(_) => (),
+ Err(e) => {
+ match e {
+ daemonize::DaemonizeError::LockPidfile(_) => {
+ // this means that there is already an agent running, so
+ // return a special exit code to allow the cli to detect
+ // this case and not error out
+ std::process::exit(23);
+ }
+ _ => panic!("failed to daemonize: {}", e),
+ }
+ }
+ }
+
+ tokio::runtime::Runtime::new().unwrap().block_on(async {
+ let listener = make_socket();
+
+ nix::unistd::write(w, &[0]).unwrap();
+ nix::unistd::close(w).unwrap();
+
+ let mut agent = Agent::new();
+ agent.run(listener.unwrap()).await;
+ })
}