From d608ffeeda1a479c9dc0e5f6ad269ba07a510d7f Mon Sep 17 00:00:00 2001 From: Andrew Guschin Date: Fri, 30 Oct 2026 03:10:41 +0400 Subject: Implement Linux proxy controller, subscription state, and CLI/TUI --- src/authentication.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/authentication.rs (limited to 'src/authentication.rs') diff --git a/src/authentication.rs b/src/authentication.rs new file mode 100644 index 0000000..5312792 --- /dev/null +++ b/src/authentication.rs @@ -0,0 +1,52 @@ +use anyhow::{Context, Result}; +use std::{ + io::Read, + os::fd::AsRawFd, + process::{Child, Command, Stdio}, + time::Duration, +}; + +pub struct TerminalAgent(Option); +impl TerminalAgent { + pub fn start(interactive: bool) -> Result { + if !interactive || unsafe { libc::geteuid() } == 0 { + return Ok(Self(None)); + } + let (mut reader, writer) = std::os::unix::net::UnixStream::pair()?; + reader.set_read_timeout(Some(Duration::from_secs(5)))?; + let fd = writer.as_raw_fd(); + // SAFETY: fd belongs to writer and remains open until after spawning the agent. + unsafe { + libc::fcntl(fd, libc::F_SETFD, 0); + } + let mut child = Command::new("/usr/bin/pkttyagent") + .args([ + "--process", + &std::process::id().to_string(), + "--notify-fd", + &fd.to_string(), + "--fallback", + ]) + .stdin(Stdio::inherit()) + .stdout(Stdio::inherit()) + .stderr(Stdio::inherit()) + .spawn() + .context("Could not start terminal polkit agent; install polkit")?; + drop(writer); + let mut buffer = [0u8; 1]; + if let Err(error) = reader.read(&mut buffer) { + let _ = child.kill(); + let _ = child.wait(); + return Err(error).context("Terminal authentication agent did not become ready"); + } + Ok(Self(Some(child))) + } +} +impl Drop for TerminalAgent { + fn drop(&mut self) { + if let Some(child) = &mut self.0 { + let _ = child.kill(); + let _ = child.wait(); + } + } +} -- cgit v1.2.3