Skip to content
Closed
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
5 changes: 4 additions & 1 deletion bin/omarchy-dev-link
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ done
# Staged and parsed before anything is installed: a sudoers file sudo refuses to
# read takes every rule after it down with it, including the %wheel grant, and
# the password prompt needed to undo that is on the other side of the breakage.
staged_sudoers=$(mktemp)
# Keep the draft out of world-writable /tmp; visudo -cf reads it before install.
stage_dir="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$stage_dir"
staged_sudoers=$(mktemp "$stage_dir/omarchy-dev-path.XXXXXX")
trap 'rm -f "$staged_sudoers"' EXIT

{
Expand Down
6 changes: 4 additions & 2 deletions bin/omarchy-hyprland-monitor-watch
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
# omarchy:summary=Watch Hyprland monitor events and recover monitor toggles when a monitor is removed

SOCKET="$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock"
LOCK="${XDG_RUNTIME_DIR:-/tmp}/omarchy-monitor-clamshell.lock"
MODELESS_LOCK="${XDG_RUNTIME_DIR:-/tmp}/omarchy-monitor-modeless.lock"
LOCK_DIR="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$LOCK_DIR"
LOCK="$LOCK_DIR/omarchy-monitor-clamshell.lock"
MODELESS_LOCK="$LOCK_DIR/omarchy-monitor-modeless.lock"

sync_clamshell() {
(
Expand Down
10 changes: 6 additions & 4 deletions bin/omarchy-menu-images
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,12 @@ if (( ${#image_dirs[@]} == 0 )); then
exit 1
fi

selection_file=$(mktemp)
done_file=$(mktemp)
pending_file=$(mktemp)
pending_video_file=$(mktemp)
ipc_dir="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$ipc_dir"
selection_file=$(mktemp "$ipc_dir/omarchy-menu-images.XXXXXX")
done_file=$(mktemp "$ipc_dir/omarchy-menu-images.XXXXXX")
pending_file=$(mktemp "$ipc_dir/omarchy-menu-images.XXXXXX")
pending_video_file=$(mktemp "$ipc_dir/omarchy-menu-images.XXXXXX")
rm -f "$done_file"
trap 'rm -f "$selection_file" "$done_file" "$pending_file" "$pending_video_file"' EXIT

Expand Down
6 changes: 4 additions & 2 deletions bin/omarchy-menu-input
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ while (( $# > 0 )); do
shift
done

selection_file=$(mktemp)
done_file=$(mktemp)
ipc_dir="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$ipc_dir"
selection_file=$(mktemp "$ipc_dir/omarchy-menu-input.XXXXXX")
done_file=$(mktemp "$ipc_dir/omarchy-menu-input.XXXXXX")
rm -f "$done_file"
trap 'rm -f "$selection_file" "$done_file"' EXIT

Expand Down
6 changes: 4 additions & 2 deletions bin/omarchy-menu-select
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,10 @@ if (( ${#options[@]} == 0 )); then
exit 1
fi

selection_file=$(mktemp)
done_file=$(mktemp)
ipc_dir="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$ipc_dir"
selection_file=$(mktemp "$ipc_dir/omarchy-menu-select.XXXXXX")
done_file=$(mktemp "$ipc_dir/omarchy-menu-select.XXXXXX")
rm -f "$done_file"
trap 'rm -f "$selection_file" "$done_file"' EXIT

Expand Down
11 changes: 9 additions & 2 deletions bin/omarchy-system-lock
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,18 @@ hyprctl switchxkblayout all 0 > /dev/null 2>&1

# Ensure 1password is locked. Use timeout because `1password --lock` can
# otherwise leave a full Electron helper tree running after each lock.
# Keep the flock out of world-writable /tmp: a held lock there used to make
# `flock -n || exit 0` skip `--lock`. If the private lock file cannot be
# created, still lock.
if pgrep -x "1password" >/dev/null && omarchy-cmd-present 1password; then
(
flock -n 9 || exit 0
lock_dir="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
lock_file="$lock_dir/omarchy-1password-lock.lock"
if mkdir -m 700 -p "$lock_dir" && exec 9>"$lock_file"; then
flock -n 9 || exit 0
fi
timeout --kill-after=1s 3s 1password --lock >/dev/null 2>&1 || true
) 9>"${XDG_RUNTIME_DIR:-/tmp}/omarchy-1password-lock.lock" &
) &
fi

# Avoid running screensaver when locked
Expand Down
4 changes: 3 additions & 1 deletion bin/omarchy-theme-set
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ CURRENT_THEME_PATH="$HOME/.local/state/omarchy/current/theme"
NEXT_THEME_PATH="$HOME/.local/state/omarchy/current/next-theme"
CURRENT_BACKGROUND_LINK="$HOME/.local/state/omarchy/current/background"
BACKGROUND_TRANSITION_CACHE="$HOME/.cache/omarchy/background-transitions"
THEME_SET_LOCK="${XDG_RUNTIME_DIR:-/tmp}/omarchy-theme-set.lock"
THEME_SET_LOCK_DIR="${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}"
mkdir -m 700 -p "$THEME_SET_LOCK_DIR"
THEME_SET_LOCK="$THEME_SET_LOCK_DIR/omarchy-theme-set.lock"
USER_THEMES_PATH="$HOME/.config/omarchy/themes"
OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes"

Expand Down
30 changes: 30 additions & 0 deletions test/shell.d/dev-link-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,26 @@ printf 'reboot\n' >>"$OMARCHY_DEV_LINK_TEST_LOG"
SH
chmod +x "$stub_bin/omarchy-system-reboot"

cat >"$stub_bin/realpath" <<'SH'
#!/bin/bash
while (( $# )); do
case "$1" in
-e|--canonicalize-existing) shift ;;
-*) shift ;;
*) break ;;
esac
done
[[ -n ${1:-} && -e $1 ]] || exit 1
printf '%s\n' "$1"
SH
chmod +x "$stub_bin/realpath"

runtime_dir="$test_tmp/runtime"
mkdir -m 700 -p "$runtime_dir"

run_link() {
HOME="$test_tmp/home" \
XDG_RUNTIME_DIR="$runtime_dir" \
OMARCHY_DEV_LINK_TEST_LOG="$log_file" \
OMARCHY_DEV_LINK_TEST_CONF="$conf_file" \
OMARCHY_DEV_LINK_TEST_SUDOERS="$sudoers_file" \
Expand Down Expand Up @@ -88,6 +106,18 @@ grep -Eq $'^sudo\tinstall\t-Dm440\t-o\troot\t-g\troot\t[^\t]+\t/etc/sudoers\\.d/
fail "dev link installs the drop-in root-owned and read-only" "$(cat "$log_file")"
pass "dev link installs the drop-in root-owned and read-only"

staged_path=$(awk -F '\t' '$1 == "sudo" && $2 == "install" { print $(NF-1) }' "$log_file")
[[ $staged_path == "$runtime_dir"/omarchy-dev-path.* ]] ||
fail "dev link stages sudoers under XDG_RUNTIME_DIR" "$(cat "$log_file")"
pass "dev link stages sudoers under XDG_RUNTIME_DIR"

if grep -Fq 'staged_sudoers=$(mktemp)' "$ROOT/bin/omarchy-dev-link"; then
fail "dev link must not mktemp sudoers in the default /tmp"
fi
grep -Fq '${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}' "$ROOT/bin/omarchy-dev-link" ||
fail "dev link falls back to a 0700 /tmp/omarchy-\$UID directory"
pass "dev link does not stage sudoers in world-writable /tmp"

visudo -cf "$sudoers_file" >/dev/null ||
fail "dev link writes a sudoers drop-in sudo can parse" "$(<"$sudoers_file")"
pass "dev link writes a sudoers drop-in sudo can parse"
Expand Down
70 changes: 70 additions & 0 deletions test/shell.d/menu-ipc-path-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/bin/bash

set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"

require_command perl

tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT

runtime_dir="$tmpdir/runtime"
stub_bin="$tmpdir/bin"
ipc_log="$tmpdir/ipc.log"
mkdir -m 700 -p "$runtime_dir" "$stub_bin"

cat >"$stub_bin/omarchy-shell" <<'SH'
#!/bin/bash
payload="${@: -1}"
perl -MJSON::PP=decode_json -e '
my $p = decode_json($ARGV[0]);
my $sel = $p->{selectionFile};
my $done = $p->{doneFile};
die "missing ipc paths" unless defined $sel && defined $done;
if (defined $ENV{IPC_LOG}) {
open my $l, ">>", $ENV{IPC_LOG} or die $!;
print $l "$sel\n$done\n";
close $l;
}
open my $s, ">", $sel or die $!;
print $s "picked\n";
close $s;
open my $d, ">", $done or die $!;
close $d;
' "$payload"
SH
chmod +x "$stub_bin/omarchy-shell"

for cmd in omarchy-menu-select omarchy-menu-input omarchy-menu-images; do
if grep -E '^selection_file=\$\(mktemp\)$' "$ROOT/bin/$cmd"; then
fail "$cmd must not mktemp in the default /tmp"
fi
grep -Fq '${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}' "$ROOT/bin/$cmd" ||
fail "$cmd stages menu IPC under the runtime directory"
done
pass "menu helpers do not stage IPC files in world-writable /tmp"

: >"$ipc_log"
PATH="$stub_bin:$PATH" XDG_RUNTIME_DIR="$runtime_dir" IPC_LOG="$ipc_log" \
"$ROOT/bin/omarchy-menu-select" Prompt one >"$tmpdir/select.out"

[[ $(<"$tmpdir/select.out") == picked ]] ||
fail "menu-select still returns the chosen row" "$(<"$tmpdir/select.out")"
while IFS= read -r path; do
[[ $path == "$runtime_dir"/omarchy-menu-select.* ]] ||
fail "menu-select IPC path is under XDG_RUNTIME_DIR" "$path"
done <"$ipc_log"
pass "menu-select stages IPC under XDG_RUNTIME_DIR"

: >"$ipc_log"
PATH="$stub_bin:$PATH" XDG_RUNTIME_DIR="$runtime_dir" IPC_LOG="$ipc_log" \
"$ROOT/bin/omarchy-menu-input" Reminder >"$tmpdir/input.out"

[[ $(<"$tmpdir/input.out") == picked ]] ||
fail "menu-input still returns the typed value" "$(<"$tmpdir/input.out")"
while IFS= read -r path; do
[[ $path == "$runtime_dir"/omarchy-menu-input.* ]] ||
fail "menu-input IPC path is under XDG_RUNTIME_DIR" "$path"
done <"$ipc_log"
pass "menu-input stages IPC under XDG_RUNTIME_DIR"
10 changes: 10 additions & 0 deletions test/shell.d/monitor-recovery-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ grep -F 'flock -n 9' "$monitor_watch" >/dev/null
grep -F 'omarchy-hyprland-monitor-clamshell' "$monitor_watch" >/dev/null
pass "monitor watcher retries internal monitor recovery after removal"

if grep -Fq '${XDG_RUNTIME_DIR:-/tmp}/omarchy-monitor-clamshell.lock' "$monitor_watch" ||
grep -Fq '${XDG_RUNTIME_DIR:-/tmp}/omarchy-monitor-modeless.lock' "$monitor_watch"; then
fail "monitor watcher flock files must not fall back to world-writable /tmp"
fi
grep -Fq '${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}' "$monitor_watch" ||
fail "monitor watcher flock falls back to a 0700 /tmp/omarchy-\$UID directory"
grep -Fq 'mkdir -m 700 -p "$LOCK_DIR"' "$monitor_watch" ||
fail "monitor watcher creates the flock directory with mode 0700"
pass "monitor watcher flock files are not in world-writable /tmp"

grep -F 'monitoradded\>\>*|monitoraddedv2\>\>*)' "$monitor_watch" >/dev/null
grep -F 'omarchy-hyprland-monitor-clamshell' "$monitor_watch" >/dev/null
pass "monitor watcher disables the internal monitor after closed-lid external hotplug"
Expand Down
49 changes: 49 additions & 0 deletions test/shell.d/system-lock-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,52 @@ mapfile -t shutdown < <(rg '^(pkill|timeout) ' "$call_log")
[[ ${shutdown[2]} == "pkill -f [o]rg.omarchy.screensaver" ]] ||
fail "system lock closes the screensaver terminal after ttfx exits" "calls: ${shutdown[*]}"
pass "system lock waits for ttfx before closing its terminal"

lock_src="$ROOT/bin/omarchy-system-lock"
if grep -Fq '${XDG_RUNTIME_DIR:-/tmp}/omarchy-1password-lock.lock' "$lock_src"; then
fail "1Password flock must not fall back to world-writable /tmp"
fi
grep -Fq '${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}' "$lock_src" ||
fail "1Password flock falls back to a 0700 /tmp/omarchy-\$UID directory"
grep -Fq 'flock -n 9 || exit 0' "$lock_src" ||
fail "1Password flock still dedupes an in-progress lock"
grep -Fq 'timeout --kill-after=1s 3s 1password --lock' "$lock_src" ||
fail "system lock still issues 1password --lock"
pass "1Password lock file is not in world-writable /tmp"

runtime_dir="$tmpdir/runtime"
mkdir -m 700 -p "$runtime_dir"
: >"$call_log"

cat >"$mock_bin/pgrep" <<'SH'
#!/bin/bash
[[ $1 == -x && $2 == 1password ]]
SH
cat >"$mock_bin/omarchy-cmd-present" <<'SH'
#!/bin/bash
[[ $1 == 1password ]]
SH
cat >"$mock_bin/1password" <<'SH'
#!/bin/bash
printf '1password %s\n' "$*" >>"$CALL_LOG"
SH
# Arch has util-linux flock; this suite also runs where it is not on PATH.
cat >"$mock_bin/flock" <<'SH'
#!/bin/bash
exit 0
SH
chmod +x "$mock_bin"/*

PATH="$mock_bin:$PATH" CALL_LOG="$call_log" XDG_RUNTIME_DIR="$runtime_dir" \
"$ROOT/bin/omarchy-system-lock"

for _ in {1..40}; do
grep -Fq 'timeout --kill-after=1s 3s 1password --lock' "$call_log" && break
sleep 0.05
done

grep -Fq 'timeout --kill-after=1s 3s 1password --lock' "$call_log" ||
fail "system lock still calls 1password --lock when 1Password is running" "$(cat "$call_log")"
[[ -e $runtime_dir/omarchy-1password-lock.lock ]] ||
fail "1Password flock is created under XDG_RUNTIME_DIR"
pass "1Password flock lives in the runtime directory"
18 changes: 18 additions & 0 deletions test/shell.d/theme-set-lock-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/bash

set -euo pipefail

source "$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"

theme_set="$ROOT/bin/omarchy-theme-set"

if grep -Fq '${XDG_RUNTIME_DIR:-/tmp}/omarchy-theme-set.lock' "$theme_set"; then
fail "theme-set flock must not fall back to world-writable /tmp"
fi
grep -Fq '${XDG_RUNTIME_DIR:-/tmp/omarchy-$UID}' "$theme_set" ||
fail "theme-set flock falls back to a 0700 /tmp/omarchy-\$UID directory"
grep -Fq 'mkdir -m 700 -p "$THEME_SET_LOCK_DIR"' "$theme_set" ||
fail "theme-set creates the flock directory with mode 0700"
grep -Fq 'THEME_SET_LOCK="$THEME_SET_LOCK_DIR/omarchy-theme-set.lock"' "$theme_set" ||
fail "theme-set keeps the flock file name"
pass "theme-set flock is not in world-writable /tmp"