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
84 changes: 84 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,90 @@

targetSystems = [ "aarch64-linux" "x86_64-linux" ];
in {
packages = nixpkgs.lib.genAttrs targetSystems (system:
let
pkgs = pkgsFor system;
mkSwhkd = { withRfkill ? true }: pkgs.rustPlatform.buildRustPackage {
pname = "swhkd";
version =
let
cargoToml = builtins.fromTOML (builtins.readFile ./swhkd/Cargo.toml);
in cargoToml.package.version;

src = ./.;

cargoLock = {
lockFile = ./Cargo.lock;
outputHashes = {
"sweet-0.4.0" = "sha256-Ky2afQ5HyO1a6YT8Jjl6az1jczq+MBKeuRmFwmcvg6U=";
};
};

nativeBuildInputs = with pkgs; [
pkg-config
scdoc
];

buildInputs = with pkgs; [
udev
];

# Build specific workspace members
buildAndTestSubdir = null; # We're building from workspace root

# Override the build phase to build specific binaries
buildPhase = ''
runHook preBuild
cargo build --release --bin swhkd --features no_rfkill
cargo build --release --bin swhkd ${pkgs.lib.optionalString (!withRfkill) "--features no_rfkill"}
cargo build --release --bin swhks
runHook postBuild
'';

# Don't run tests during build
# doCheck = false;

postBuild = ''
# Generate man pages from .scd files
for f in docs/*.scd; do
if [ -f "$f" ]; then
target="''${f%.scd}"
scdoc < "$f" | gzip > "$target.gz"
fi
done
'';

installPhase = ''
runHook preInstall

# Install binaries
install -Dm755 target/release/swhkd $out/bin/swhkd
install -Dm755 target/release/swhks $out/bin/swhks

# Install man pages
find ./docs -type f -name "*.1.gz" \
-exec install -Dm644 {} -t $out/share/man/man1 \;
find ./docs -type f -name "*.5.gz" \
-exec install -Dm644 {} -t $out/share/man/man5 \;

runHook postInstall
'';

meta = with pkgs.lib; {
description = "Simple Wayland HotKey Daemon";
homepage = "https://github.com/waycrate/swhkd";
license = licenses.bsd2;
platforms = platforms.linux;
mainProgram = "swhkd";
};
};
in {
swhkd = mkSwhkd { withRfkill = true; };
swhkd-no-rfkill = mkSwhkd { withRfkill = false; };
default = self.packages.${system}.swhkd;

});

devShells = nixpkgs.lib.genAttrs targetSystems (system:
let pkgs = pkgsFor system;
in {
Expand Down
21 changes: 13 additions & 8 deletions swhkd/src/daemon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ use config::Hotkey;
use evdev::{AttributeSet, Device, InputEventKind, Key};
use nix::{
sys::stat::{umask, Mode},
unistd::{setgid, setuid, Gid, Uid},
unistd::{setgid, setuid, Gid, Uid, User},
};
use signal_hook::consts::signal::*;
use signal_hook_tokio::Signals;
use std::{
collections::{HashMap, HashSet},
env,
error::Error,
ffi::CString,
fs::{self, File, OpenOptions, Permissions},
io::{Read, Write},
os::unix::{fs::PermissionsExt, net::UnixStream},
os::unix::{fs::PermissionsExt, net::UnixStream, process::CommandExt},
path::{Path, PathBuf},
process::{exit, id, Command, Stdio},
sync::{Arc, Mutex},
Expand Down Expand Up @@ -194,16 +195,20 @@ async fn main() -> Result<(), Box<dyn Error>> {
let pairs = pairs.clone();
let log = log.clone();

// Set the user and group id to the invoking user for the thread
setgid(Gid::from_raw(invoking_uid))
.expect(&format!("Failed to set group-id to {}", invoking_uid));
setuid(Uid::from_raw(invoking_uid))
.expect(&format!("Failed to set user-id to {}", invoking_uid));
// Command execution with user privileges
let user_uid = Uid::from_raw(invoking_uid);
let user = User::from_uid(user_uid)
.expect("Failed to get user info")
.expect(&format!("User with UID {} not found", invoking_uid));

let username =
CString::new(user.name.as_str()).expect("Failed to convert username to CString");

// Command execution
let mut cmd = Command::new("sh");
cmd.arg("-c")
.arg(command)
.uid(invoking_uid)
.gid(user.gid.as_raw())
.stdin(Stdio::null())
.stdout(match File::open(&log) {
Ok(file) => file,
Expand Down
5 changes: 3 additions & 2 deletions swhkd/src/perms.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use nix::unistd::{Gid, Uid, User};
use std::process::exit;
use std::{ffi::CString, process::exit};

pub fn _drop_privileges(user_uid: u32) {
let user_uid = Uid::from_raw(user_uid);
Expand All @@ -20,7 +20,8 @@ pub fn raise_privileges() {

fn set_initgroups(user: &nix::unistd::User, gid: u32) {
let gid = Gid::from_raw(gid);
match nix::unistd::initgroups(&user.gecos, gid) {
let username = CString::new(user.name.as_str()).expect("Failed to convert username to CString");
match nix::unistd::initgroups(&username, gid) {
Ok(_) => log::debug!("Setting initgroups..."),
Err(e) => {
log::error!("Failed to set init groups: {:#?}", e);
Expand Down