Compare commits

...
11 Commits
Author SHA1 Message Date
odweta 3b0a5ceb26 update slock 2026-11-05 15:22:19 +01:00
odweta 01ea2e89f2 update ig 2026-11-05 15:20:33 +01:00
odweta e9e8ad1b67 update suckless 2026-10-25 04:40:51 +01:00
odweta 05c1337f0b update xinitrc 2026-10-24 21:43:22 +02:00
odweta 038b140f26 update xinitrc 2026-10-24 21:40:52 +02:00
odweta c4d7e415fa update config 2026-10-20 19:43:16 +02:00
odweta 9d42049837 update xinitrc and added natural scrolling and force dark GTK theming 2026-10-20 18:24:33 +02:00
odweta dc3c51f19e update: dmenu and add setxkbmap 2026-09-27 12:09:07 +02:00
odweta 0105696f5e update: README with nix things 2026-09-27 11:34:14 +02:00
odweta d609266cdb fix: turn off bluetooth on every session start 2026-09-27 11:31:06 +02:00
odweta 6685c91106 update: make xbinds update dwmblocks 2026-09-27 11:30:41 +02:00
39 changed files with 1572 additions and 97 deletions
+4 -1
View File
@@ -141,6 +141,9 @@ PROMPT_COMMAND=__tokyo_prompt
export PATH=$PATH:$HOME/containers/bin export PATH=$PATH:$HOME/containers/bin
if [ -z $DISPLAY ]; then
startx
fi
clear clear
ofetch ofetch
+5 -5
View File
@@ -1,23 +1,23 @@
# ~/.xbindkeysrc # ~/.xbindkeysrc
# Volume mute # Volume mute
"wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle" "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle; pkill -RTMIN+2 dwmblocks"
XF86AudioMute XF86AudioMute
# Volume down # Volume down
"wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-" "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-; pkill -RTMIN+2 dwmblocks"
XF86AudioLowerVolume XF86AudioLowerVolume
# Volume up # Volume up
"wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+" "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+; pkill -RTMIN+2 dwmblocks"
XF86AudioRaiseVolume XF86AudioRaiseVolume
# Brightness down # Brightness down
"brightnessctl set 5%-" "brightnessctl set 5%-; pkill -RTMIN+2 dwmblocks"
XF86MonBrightnessDown XF86MonBrightnessDown
# Brightness up # Brightness up
"brightnessctl set 5%+" "brightnessctl set 5%+; pkill -RTMIN+2 dwmblocks"
XF86MonBrightnessUp XF86MonBrightnessUp
+70 -22
View File
@@ -1,29 +1,77 @@
dwmblocks & #!/bin/sh
xbindkeys &
picom &
xss-lock -l slock &
feh --bg-scale $HOME/Pictures/wallpapers/glados.jpg &
export DISPLAY=:0 # Start a D-Bus session if one is not already available
export XAUTHORITY=/home/imp/.Xauthority if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ]; then
exec dbus-run-session -- "$0" "$@"
fi
xrandr --output DP-2-1 --off # GTK Theming
sleep 2 export GTK_THEME=Adwaita:dark
# Set up monitors. Confirm these names with: xrandr --query
xrandr \ xrandr \
--output eDP-1 \ --output eDP-1 --mode 1920x1080 --rate 60 --primary \
--mode 1920x1080 \ --output DP-2-1 --mode 1920x1080 --same-as eDP-1
--rate 60 \
--pos 0x0 \
--primary \
--output DP-2-1 \
--mode 1920x1080 \
--rate 60 \
--pos 0x0 \
--same-as eDP-1
xset dpms force on # Set the keyboard layouts
setxkbmap -layout "us,cz" -variant ",qwerty" -option "grp:alt_shift_toggle"
exec dwm # Natural scrolling for the touchpad (requires xinput and the libinput driver)
xinput list --name-only | while IFS= read -r device; do
case "$device" in
*[Tt]ouch[Pp]ad*)
xinput set-prop "$device" "libinput Natural Scrolling Enabled" 1 2>/dev/null
;;
esac
done
systemctl --user restart wireplumber pipewire pipewire-pulse; pkill -RTMIN+2 dwmblocks dwmblocks &
# i really need it :(
export GPG_TTY=$(tty)
exec dbus-run-session -- sh -c '
export GPG_TTY=$(tty)
export PATH=$HOME/.local/bin:$PATH
if ! pgrep -a -u "$(id -u)" -x pipewire >/dev/null 2>&1; then
pipewire &
fi
sleep 1
pkill -RTMIN+2 dwmblocks
# Start desktop services
bluetoothctl power off &
if ! pgrep -a -u "$(id -u)" -x picom >/dev/null 2>&1; then
picom --backend glx &
fi
if ! pgrep -a -u "$(id -u)" -x dunst >/dev/null 2>&1; then
dunst &
fi
if ! pgrep -a -u "$(id -u)" -x mpv >/dev/null 2>&1; then
mpv --shuffle --pause --no-video --loop-playlist -ao=alsa $HOME/Music &
fi
if ! pgrep -a -u "$(id -u)" -x mpv-shuffle-notify >/dev/null 2>&1; then
mpv-shuffle-notify &
fi
if ! pgrep -a -u "$(id -u)" -x sxhkd >/dev/null 2>&1; then
sxhkd &
fi
xbindkeys &
# xss-lock -l slock &
if ! pgrep -a -u "$(id -u)" -x xss-lock >/dev/null 2>&1; then
xss-lock -- \
env XSECURELOCK_AUTHPROTO=authproto_pam \
XSECURELOCK_PAM_SERVICE=login \
XSECURELOCK_NO_PAM_RHOST=1 \
xsecurelock &
fi
feh --bg-scale "$HOME/Pictures/wallpapers/glados.jpg" &
exec dwm
'
+7 -1
View File
@@ -12,8 +12,14 @@
+ Dracula + Dracula
## Dependencies
1. Either install `nix` and run `nix develop` inside the repo or
2. Install the deps listed in the flake.nix file
## Usage ## Usage
1. Clone with: `git clone https://gitlab.com/odweta/suckless $HOME/.config/suckless` 1. Clone with: `git clone https://gitlab.com/odweta/suckless $HOME/.config/suckless`
2. Change into that directory with `cd $HOME/.config/suckless` 2. Change into that directory with `cd $HOME/.config/suckless`
3. Install with `./install.sh` 3. Enter the development environment with `nix develop`
4. Install with `./install.sh`
+6 -2
View File
@@ -28,7 +28,7 @@ clean:
dist: clean dist: clean
mkdir -p dmenu-$(VERSION) mkdir -p dmenu-$(VERSION)
cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1\ cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1\
drw.h util.h dmenu_path dmenu_run stest.1 $(SRC)\ drw.h util.h dmenu_path dmenu_path_desktop dmenu_run dmenu_run_desktop stest.1 $(SRC)\
dmenu-$(VERSION) dmenu-$(VERSION)
tar -cf dmenu-$(VERSION).tar dmenu-$(VERSION) tar -cf dmenu-$(VERSION).tar dmenu-$(VERSION)
gzip dmenu-$(VERSION).tar gzip dmenu-$(VERSION).tar
@@ -36,10 +36,12 @@ dist: clean
install: all install: all
mkdir -p $(DESTDIR)$(PREFIX)/bin mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin cp -f dmenu dmenu_path dmenu_path_desktop dmenu_run dmenu_run_desktop stest $(DESTDIR)$(PREFIX)/bin
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path_desktop
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run_desktop
chmod 755 $(DESTDIR)$(PREFIX)/bin/stest chmod 755 $(DESTDIR)$(PREFIX)/bin/stest
mkdir -p $(DESTDIR)$(MANPREFIX)/man1 mkdir -p $(DESTDIR)$(MANPREFIX)/man1
sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1 sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1
@@ -50,7 +52,9 @@ install: all
uninstall: uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\ rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\
$(DESTDIR)$(PREFIX)/bin/dmenu_path\ $(DESTDIR)$(PREFIX)/bin/dmenu_path\
$(DESTDIR)$(PREFIX)/bin/dmenu_path_desktop\
$(DESTDIR)$(PREFIX)/bin/dmenu_run\ $(DESTDIR)$(PREFIX)/bin/dmenu_run\
$(DESTDIR)$(PREFIX)/bin/dmenu_run_desktop\
$(DESTDIR)$(PREFIX)/bin/stest\ $(DESTDIR)$(PREFIX)/bin/stest\
$(DESTDIR)$(MANPREFIX)/man1/dmenu.1\ $(DESTDIR)$(MANPREFIX)/man1/dmenu.1\
$(DESTDIR)$(MANPREFIX)/man1/stest.1 $(DESTDIR)$(MANPREFIX)/man1/stest.1
+2 -2
View File
@@ -17,8 +17,8 @@ static const char *colors[SchemeLast][2] = {
[SchemePrompt] = { "#444444", "#222222" }, [SchemePrompt] = { "#444444", "#222222" },
}; };
/* -l and -g options; controls number of lines and columns in grid if > 0 */ /* -l and -g options; controls number of lines and columns in grid if > 0 */
static unsigned int lines = 0; static unsigned int lines = 5;
static unsigned int columns = 0; static unsigned int columns = 2;
/* /*
* Characters not considered part of a word while deleting words * Characters not considered part of a word while deleting words
+2 -2
View File
@@ -17,8 +17,8 @@ static const char *colors[SchemeLast][2] = {
[SchemePrompt] = { "#444444", "#222222" }, [SchemePrompt] = { "#444444", "#222222" },
}; };
/* -l and -g options; controls number of lines and columns in grid if > 0 */ /* -l and -g options; controls number of lines and columns in grid if > 0 */
static unsigned int lines = 0; static unsigned int lines = 5;
static unsigned int columns = 0; static unsigned int columns = 2;
/* /*
* Characters not considered part of a word while deleting words * Characters not considered part of a word while deleting words
+2
View File
@@ -1,6 +1,8 @@
# dmenu version # dmenu version
VERSION = 5.4-odweta VERSION = 5.4-odweta
PKG_CONFIG := pkg-config
# paths # paths
PREFIX = /usr PREFIX = /usr
MANPREFIX = $(PREFIX)/share/man MANPREFIX = $(PREFIX)/share/man
Executable → Regular
View File
+18
View File
@@ -0,0 +1,18 @@
#!/bin/sh
cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}"
cache="$cachedir/dmenu_run_desktop"
[ ! -e "$cachedir" ] && mkdir -p "$cachedir"
dirs=""
IFS=:
for dir in "${XDG_DATA_DIRS:-"/usr/local/share:/usr/share"}"; do
dirs="${dirs}:${dir}/applications"
done;
if stest -dqr -n "$cache" $PATH; then
stest -fl $dirs | grep -v 'mimeinfo.cache' | sed 's/\.[^./]*$//' | sort -u | tee "$cache"
else
cat "$cache"
fi
Executable → Regular
View File
+13
View File
@@ -0,0 +1,13 @@
#!/bin/sh
{
dmenu_path_desktop
find /var/lib/flatpak/exports/share/applications \
"$HOME/.local/share/flatpak/exports/share/applications" \
-maxdepth 1 -name '*.desktop' -printf '%f\n' 2>/dev/null |
sed 's/\.desktop$//' #| awk -F "." '{print $NF}' | tr '[:upper:]' '[:lower:]'
} |
sort -u |
dmenu "$@" |
xargs -r gtk-launch &
+86
View File
@@ -0,0 +1,86 @@
From fada397413584331798a1a9b8703a10110450889 Mon Sep 17 00:00:00 2001
From: Robert Bilski <robert@rbilski.com>
Date: Sun, 4 Aug 2024 22:07:35 +0200
Subject: [PATCH] Handle .desktop files
Retrieve files from applications/ and open them using gtk-launch
---
Makefile | 8 ++++++--
dmenu_path_desktop | 18 ++++++++++++++++++
dmenu_run_desktop | 2 ++
3 files changed, 26 insertions(+), 2 deletions(-)
create mode 100755 dmenu_path_desktop
create mode 100755 dmenu_run_desktop
diff --git a/Makefile b/Makefile
index 458c524..f157bb1 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@ clean:
dist: clean
mkdir -p dmenu-$(VERSION)
cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1\
- drw.h util.h dmenu_path dmenu_run stest.1 $(SRC)\
+ drw.h util.h dmenu_path dmenu_path_desktop dmenu_run dmenu_run_desktop stest.1 $(SRC)\
dmenu-$(VERSION)
tar -cf dmenu-$(VERSION).tar dmenu-$(VERSION)
gzip dmenu-$(VERSION).tar
@@ -36,10 +36,12 @@ dist: clean
install: all
mkdir -p $(DESTDIR)$(PREFIX)/bin
- cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin
+ cp -f dmenu dmenu_path dmenu_path_desktop dmenu_run dmenu_run_desktop stest $(DESTDIR)$(PREFIX)/bin
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path
+ chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path_desktop
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run
+ chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run_desktop
chmod 755 $(DESTDIR)$(PREFIX)/bin/stest
mkdir -p $(DESTDIR)$(MANPREFIX)/man1
sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1
@@ -50,7 +52,9 @@ install: all
uninstall:
rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\
$(DESTDIR)$(PREFIX)/bin/dmenu_path\
+ $(DESTDIR)$(PREFIX)/bin/dmenu_path_desktop\
$(DESTDIR)$(PREFIX)/bin/dmenu_run\
+ $(DESTDIR)$(PREFIX)/bin/dmenu_run_desktop\
$(DESTDIR)$(PREFIX)/bin/stest\
$(DESTDIR)$(MANPREFIX)/man1/dmenu.1\
$(DESTDIR)$(MANPREFIX)/man1/stest.1
diff --git a/dmenu_path_desktop b/dmenu_path_desktop
new file mode 100755
index 0000000..5ff74b3
--- /dev/null
+++ b/dmenu_path_desktop
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}"
+cache="$cachedir/dmenu_run_desktop"
+
+[ ! -e "$cachedir" ] && mkdir -p "$cachedir"
+
+dirs=""
+IFS=:
+for dir in "${XDG_DATA_DIRS:-"/usr/local/share:/usr/share"}"; do
+ dirs="${dirs}:${dir}/applications"
+done;
+
+if stest -dqr -n "$cache" $PATH; then
+ stest -fl $dirs | grep -v 'mimeinfo.cache' | sed 's/\.[^./]*$//' | sort -u | tee "$cache"
+else
+ cat "$cache"
+fi
diff --git a/dmenu_run_desktop b/dmenu_run_desktop
new file mode 100755
index 0000000..a90aceb
--- /dev/null
+++ b/dmenu_run_desktop
@@ -0,0 +1,2 @@
+#!/bin/sh
+dmenu_path_desktop | dmenu "$@" | xargs gtk-launch &
--
2.46.0
+31 -5
View File
@@ -6,14 +6,40 @@ static const int topbar = 1; /* 0 means bottom bar */
#define MAIN_FONT "JetBrainsMono Nerd Font Propo:size=14" #define MAIN_FONT "JetBrainsMono Nerd Font Propo:size=14"
static const char *fonts[] = { MAIN_FONT }; static const char *fonts[] = { MAIN_FONT };
static const char dmenufont[] = MAIN_FONT; static const char dmenufont[] = MAIN_FONT;
static const char col_gray1[] = "#222222";
static const char col_gray2[] = "#444444"; /* Gruvbox */
static const char col_gray3[] = "#bbbbbb"; static const char col_gray1[] = "#1d2021"; /* hard dark background */
static const char col_gray4[] = "#eeeeee"; static const char col_gray2[] = "#504945"; /* inactive border */
static const char col_main[] = "#735e97"; static const char col_gray3[] = "#ebdbb2"; /* normal text */
static const char col_gray4[] = "#ebdbb2"; /* selected text */
static const char col_main[] = "#3c3836"; /* muted selected background */
static const char *colors[][3] = { static const char *colors[][3] = {
/* fg bg border */ /* fg bg border */
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 }, [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_main, col_main }, [SchemeSel] = { col_gray4, col_main, col_main },
}; };
// static const char col_gray1[] = "#1d2021"; /* hard dark background */
// static const char col_gray2[] = "#504945"; /* inactive border */
// static const char col_gray3[] = "#ebdbb2"; /* normal text */
// static const char col_gray4[] = "#1d2021"; /* selected text */
// static const char col_main[] = "#d79921"; /* selected background */
//
// static const char *colors[][3] = {
// /* fg bg border */
// [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
// [SchemeSel] = { col_gray4, col_main, col_main },
// };
/* dracula */
// static const char col_gray1[] = "#222222";
// static const char col_gray2[] = "#444444";
// static const char col_gray3[] = "#bbbbbb";
// static const char col_gray4[] = "#eeeeee";
// static const char col_main[] = "#735e97";
// static const char *colors[][3] = {
// /* fg bg border */
// [SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
// [SchemeSel] = { col_gray4, col_main, col_main },
// };
//
+15 -1
View File
@@ -1,7 +1,21 @@
/* commands */ /* commands */
// static const char *dmenucmd[] =
// { "sh", "-c",
// "export XDG_DATA_DIRS="
// "\"$HOME/.local/share/flatpak/exports/share:"
// "/var/lib/flatpak/exports/share:"
// "${XDG_DATA_DIRS:-/usr/local/share:/usr/share}\"; "
// "exec dmenu_run_desktop \"$@\"",
// "dmenu_run_desktop",
// "-p", "launch an app:",
// "-l", "10", "-g", "2",
// "-m", dmenumon, "-fn", dmenufont,
// "-nb", col_gray1, "-nf", col_gray3,
// "-sb", col_main, "-sf", col_gray4,
// NULL };
static const char *dmenucmd[] = static const char *dmenucmd[] =
{ "dmenu_run", "-p", "launch an app:", { "dmenu_run_desktop", "-p", "launch an app:",
"-l", "10", "-g", "2", "-l", "10", "-g", "2",
"-m", dmenumon, "-fn", dmenufont, "-m", dmenumon, "-fn", dmenufont,
"-nb", col_gray1, "-nf", col_gray3, "-nb", col_gray1, "-nf", col_gray3,
+1 -1
View File
@@ -15,7 +15,7 @@ static const Key keys[] = {
// essential apps // essential apps
{ MODKEY, XK_space, spawn, {.v = dmenucmd } }, { MODKEY, XK_space, spawn, {.v = dmenucmd } },
{ MODKEY, XK_Return, spawn, {.v = termcmd } }, { MODKEY, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_m, spawn, {.v = djcmd } }, // { MODKEY, XK_m, spawn, {.v = djcmd } },
{ MODKEY, XK_w, spawn, {.v = webbrowsercmd } }, { MODKEY, XK_w, spawn, {.v = webbrowsercmd } },
// window management // window management
{ MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_j, focusstack, {.i = +1 } },
+1 -1
View File
@@ -10,7 +10,7 @@ const char *spcmd0[] = {"st", "-n", "spterm", "-g", "120x34", NULL };
const char *spcmd1[] = {"thunar", NULL }; const char *spcmd1[] = {"thunar", NULL };
const char *spcmd2[] = {"keepassxc", NULL }; const char *spcmd2[] = {"keepassxc", NULL };
const char *spcmd3[] = {"st", "-n", "spnmtui", "-g", "140x30", "-e", "nmtui", NULL }; const char *spcmd3[] = {"st", "-n", "spnmtui", "-g", "140x30", "-e", "nmtui", NULL };
const char *spcmd4[] = {"st", "-n", "spmusic", "-g", "140x30", "-e", "ncmpcpp", NULL }; const char *spcmd4[] = {"st", "-n", "spmusic", "-g", "140x30", "-e", "kew", NULL };
const char *spcmd5[] = {"signal-desktop", NULL }; const char *spcmd5[] = {"signal-desktop", NULL };
static Sp scratchpads[] = { static Sp scratchpads[] = {
Executable → Regular
View File
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
View File
Executable → Regular
+2
View File
@@ -2,6 +2,8 @@
set -e set -e
export PKG_CONFIG=pkg-config
install_module() { install_module() {
cd "$1" cd "$1"
make clean make clean
+13 -3
View File
@@ -3,10 +3,20 @@ static const char *user = "imp";
static const char *group = "imp"; static const char *group = "imp";
static const char *colorname[NUMCOLS] = { static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */ [INIT] = "#1d2021", /* Gruvbox dark hard background */
[INPUT] = "#735e97", /* during input */ [INPUT] = "#83a598", /* Gruvbox blue */
[FAILED] = "#CC3333", /* wrong password */ [FAILED] = "#fb4934", /* Gruvbox bright red */
[PAM] = "#d3869b", /* waiting for PAM */
}; };
/* treat a cleared input like a wrong password (color) */ /* treat a cleared input like a wrong password (color) */
static const int failonclear = 1; static const int failonclear = 1;
/* PAM service that's used for authentication */
static const char* pam_service = "login";
/* Background image path, should be available to the user above */
static const char* background_image = "/usr/share/backgrounds/glados.jpg";
/* time in seconds before the monitor shuts down */
static const int monitortime = 10;
+13
View File
@@ -0,0 +1,13 @@
/* user and group to drop privileges to */
static const char *user = "imp";
static const char *group = "imp";
static const char *colorname[NUMCOLS] = {
[INIT] = "#1d2021", /* Gruvbox dark hard background */
[INPUT] = "#83a598", /* Gruvbox blue */
[FAILED] = "#fb4934", /* Gruvbox bright red */
};
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
+19
View File
@@ -0,0 +1,19 @@
/* user and group to drop privileges to */
static const char *user = "imp";
static const char *group = "imp";
static const char *colorname[NUMCOLS] = {
[INIT] = "#1d2021", /* Gruvbox dark hard background */
[INPUT] = "#83a598", /* Gruvbox blue */
[FAILED] = "#fb4934", /* Gruvbox bright red */
[PAM] = "#d3869b", /* waiting for PAM */
};
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
/* PAM service that's used for authentication */
static const char* pam_service = "login";
/* Background image path, should be available to the user above */
static const char* background_image = "/usr/share/backgrounds/glados.jpg";
+9
View File
@@ -0,0 +1,9 @@
--- config.def.h
+++ config.def.h
@@ -10,3 +10,6 @@ static const char *colorname[NUMCOLS] = {
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
+
+/* time in seconds before the monitor shuts down */
+static const int monitortime = 5;
+13 -3
View File
@@ -3,10 +3,20 @@ static const char *user = "imp";
static const char *group = "imp"; static const char *group = "imp";
static const char *colorname[NUMCOLS] = { static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */ [INIT] = "#1d2021", /* Gruvbox dark hard background */
[INPUT] = "#735e97", /* during input */ [INPUT] = "#83a598", /* Gruvbox blue */
[FAILED] = "#CC3333", /* wrong password */ [FAILED] = "#fb4934", /* Gruvbox bright red */
[PAM] = "#d3869b", /* waiting for PAM */
}; };
/* treat a cleared input like a wrong password (color) */ /* treat a cleared input like a wrong password (color) */
static const int failonclear = 1; static const int failonclear = 1;
/* PAM service that's used for authentication */
static const char* pam_service = "login";
/* Background image path, should be available to the user above */
static const char* background_image = "/usr/share/backgrounds/glados.jpg";
/* time in seconds before the monitor shuts down */
static const int monitortime = 10;
+1 -1
View File
@@ -15,7 +15,7 @@ X11LIB = $(shell $(PKG_CONFIG) --libs x11 xft xrandr xinerama fontconfig freetyp
# includes and libs # includes and libs
INCS = ${X11INC} INCS = ${X11INC}
LIBS = -lc -lcrypt ${X11LIB} LIBS = -lc -lcrypt -lpam -lImlib2 -lXext ${X11LIB}
# flags # flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
+26
View File
@@ -0,0 +1,26 @@
# slock version
VERSION = 1.6-odweta
# Customize below to fit your system
# paths
PREFIX = /usr
MANPREFIX = ${PREFIX}/share/man
PKG_CONFIG := pkg-config
# compiler and linker flags
X11INC = $(shell $(PKG_CONFIG) --cflags x11 xft xrandr xinerama fontconfig freetype2)
X11LIB = $(shell $(PKG_CONFIG) --libs x11 xft xrandr xinerama fontconfig freetype2)
# includes and libs
INCS = ${X11INC}
LIBS = -lc -lcrypt -lpam ${X11LIB}
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
LDFLAGS = -s ${LIBS}
COMPATSRC = explicit_bzero.c
CC = cc
+11
View File
@@ -0,0 +1,11 @@
--- config.mk
+++ config.mk
@@ -12,7 +12,7 @@ X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I. -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr
+LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lImlib2
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
+88
View File
@@ -0,0 +1,88 @@
diff -up a/slock.c b/slock.c
--- a/slock.c 2026-07-28 03:28:03.120285888 +0530
+++ b/slock.c 2026-08-03 11:20:35.223992495 +0530
@@ -6,7 +6,9 @@
#include <ctype.h>
#include <errno.h>
+#include <fcntl.h>
#include <grp.h>
+#include <limits.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -59,7 +61,6 @@ die(const char *errstr, ...)
}
#ifdef __linux__
-#include <fcntl.h>
#include <linux/oom.h>
static void
@@ -301,6 +302,28 @@ lockscreen(Display *dpy, struct xrandr *
return NULL;
}
+static int
+get_xss_sleep_lock_fd(void)
+{
+ char *env_str, *end;
+ long env_val;
+
+ env_str = getenv("XSS_SLEEP_LOCK_FD");
+ if (!env_str || !*env_str)
+ return -1;
+
+ errno = 0;
+ env_val = strtol(env_str, &end, 10);
+ if (errno ||
+ *end ||
+ (env_val < 0 || env_val > INT_MAX)) {
+ fprintf(stderr, "slock: strtol $XSS_SLEEP_LOCK_FD: %s\n",
+ errno ? strerror(errno) : "invalid value");
+ return -1;
+ }
+ return (int)env_val;
+}
+
static void
usage(void)
{
@@ -318,6 +341,7 @@ main(int argc, char **argv) {
const char *hash;
Display *dpy;
int s, nlocks, nscreens;
+ int lockfd;
ARGBEGIN {
case 'v':
@@ -327,6 +351,18 @@ main(int argc, char **argv) {
usage();
} ARGEND
+ lockfd = get_xss_sleep_lock_fd();
+ if (lockfd >= 0) {
+ int flags = fcntl(lockfd, F_GETFD);
+ if (flags < 0) {
+ fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_GETFD: %s\n",
+ strerror(errno));
+ } else if (fcntl(lockfd, F_SETFD, flags | FD_CLOEXEC) == -1) {
+ fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_SETFD: %s\n",
+ strerror(errno));
+ }
+ }
+
/* validate drop-user and -group */
errno = 0;
if (!(pwd = getpwnam(user)))
@@ -378,6 +414,9 @@ main(int argc, char **argv) {
if (nlocks != nscreens)
return 1;
+ if (lockfd >= 0 && close(lockfd) < 0)
+ fprintf(stderr, "slock: close $XSS_SLEEP_LOCK_FD: %s\n", strerror(errno));
+
/* run post-lock command */
if (argc > 0) {
pid_t pid;
@@ -0,0 +1,150 @@
From 1c5a5383a1cf3351fe9c80a21cfbc98c5ec4355d Mon Sep 17 00:00:00 2001
From: Yan Doroshenko <yan1994doroshenko@gmail.com>
Date: Fri, 18 Mar 2022 12:28:13 +0100
Subject: [PATCH] Provide a way to set a background image
---
config.def.h | 5 ++++-
config.mk | 2 +-
slock.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/config.def.h b/config.def.h
index 9855e21..eb88b3d 100644
--- a/config.def.h
+++ b/config.def.h
@@ -1,6 +1,6 @@
/* user and group to drop privileges to */
static const char *user = "nobody";
-static const char *group = "nogroup";
+static const char *group = "nobody";
static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */
@@ -10,3 +10,6 @@ static const char *colorname[NUMCOLS] = {
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
+
+/* Background image path, should be available to the user above */
+static const char* background_image = "";
diff --git a/config.mk b/config.mk
index 74429ae..987819e 100644
--- a/config.mk
+++ b/config.mk
@@ -12,7 +12,7 @@ X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I. -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr
+LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lImlib2
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
diff --git a/slock.c b/slock.c
index 5ae738c..345a279 100644
--- a/slock.c
+++ b/slock.c
@@ -18,6 +18,7 @@
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <Imlib2.h>
#include "arg.h"
#include "util.h"
@@ -35,6 +36,7 @@ struct lock {
int screen;
Window root, win;
Pixmap pmap;
+ Pixmap bgmap;
unsigned long colors[NUMCOLS];
};
@@ -46,6 +48,8 @@ struct xrandr {
#include "config.h"
+Imlib_Image image;
+
static void
die(const char *errstr, ...)
{
@@ -190,9 +194,10 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT);
if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) {
- XSetWindowBackground(dpy,
- locks[screen]->win,
- locks[screen]->colors[color]);
+ if (locks[screen]->bgmap)
+ XSetWindowBackgroundPixmap(dpy, locks[screen]->win, locks[screen]->bgmap);
+ else
+ XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]);
XClearWindow(dpy, locks[screen]->win);
}
oldc = color;
@@ -235,6 +240,17 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
lock->screen = screen;
lock->root = RootWindow(dpy, lock->screen);
+ if(image)
+ {
+ lock->bgmap = XCreatePixmap(dpy, lock->root, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), DefaultDepth(dpy, lock->screen));
+ imlib_context_set_display(dpy);
+ imlib_context_set_visual(DefaultVisual(dpy, lock->screen));
+ imlib_context_set_colormap(DefaultColormap(dpy, lock->screen));
+ imlib_context_set_drawable(lock->bgmap);
+ imlib_render_image_on_drawable(0, 0);
+ imlib_free_image();
+ }
+
for (i = 0; i < NUMCOLS; i++) {
XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen),
colorname[i], &color, &dummy);
@@ -251,6 +267,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
CopyFromParent,
DefaultVisual(dpy, lock->screen),
CWOverrideRedirect | CWBackPixel, &wa);
+ if(lock->bgmap)
+ XSetWindowBackgroundPixmap(dpy, lock->win, lock->bgmap);
lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8);
invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap,
&color, &color, 0, 0);
@@ -355,6 +373,32 @@ main(int argc, char **argv) {
if (setuid(duid) < 0)
die("slock: setuid: %s\n", strerror(errno));
+ /* Load picture */
+ Imlib_Image buffer = imlib_load_image(background_image);
+ imlib_context_set_image(buffer);
+ int background_image_width = imlib_image_get_width();
+ int background_image_height = imlib_image_get_height();
+
+ /* Create an image to be rendered */
+ Screen *scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
+ image = imlib_create_image(scr->width, scr->height);
+ imlib_context_set_image(image);
+
+ /* Fill the image for every X monitor */
+ XRRMonitorInfo *monitors;
+ int number_of_monitors;
+ monitors = XRRGetMonitors(dpy, RootWindow(dpy, XScreenNumberOfScreen(scr)), True, &number_of_monitors);
+
+ int i;
+ for (i = 0; i < number_of_monitors; i++) {
+ imlib_blend_image_onto_image(buffer, 0, 0, 0, background_image_width, background_image_height, monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height);
+ }
+
+ /* Clean up */
+ imlib_context_set_image(buffer);
+ imlib_free_image();
+ imlib_context_set_image(image);
+
/* check for Xrandr support */
rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
--
2.35.1
+155
View File
@@ -0,0 +1,155 @@
diff --git a/config.def.h b/config.def.h
index 9855e21..19e7f62 100644
--- a/config.def.h
+++ b/config.def.h
@@ -6,7 +6,11 @@ static const char *colorname[NUMCOLS] = {
[INIT] = "black", /* after initialization */
[INPUT] = "#005577", /* during input */
[FAILED] = "#CC3333", /* wrong password */
+ [PAM] = "#9400D3", /* waiting for PAM */
};
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
+
+/* PAM service that's used for authentication */
+static const char* pam_service = "login";
diff --git a/config.mk b/config.mk
index 74429ae..6e82074 100644
--- a/config.mk
+++ b/config.mk
@@ -12,7 +12,7 @@ X11LIB = /usr/X11R6/lib
# includes and libs
INCS = -I. -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr
+LIBS = -L/usr/lib -lc -lcrypt -L${X11LIB} -lX11 -lXext -lXrandr -lpam
# flags
CPPFLAGS = -DVERSION=\"${VERSION}\" -D_DEFAULT_SOURCE -DHAVE_SHADOW_H
diff --git a/slock.c b/slock.c
index 5ae738c..3a8da42 100644
--- a/slock.c
+++ b/slock.c
@@ -18,16 +18,22 @@
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
+#include <security/pam_appl.h>
+#include <security/pam_misc.h>
#include "arg.h"
#include "util.h"
char *argv0;
+static int pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr);
+struct pam_conv pamc = {pam_conv, NULL};
+char passwd[256];
enum {
INIT,
INPUT,
FAILED,
+ PAM,
NUMCOLS
};
@@ -57,6 +63,31 @@ die(const char *errstr, ...)
exit(1);
}
+static int
+pam_conv(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr)
+{
+ int retval = PAM_CONV_ERR;
+ for(int i=0; i<num_msg; i++) {
+ if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF &&
+ strncmp(msg[i]->msg, "Password: ", 10) == 0) {
+ struct pam_response *resp_msg = malloc(sizeof(struct pam_response));
+ if (!resp_msg)
+ die("malloc failed\n");
+ char *password = malloc(strlen(passwd) + 1);
+ if (!password)
+ die("malloc failed\n");
+ memset(password, 0, strlen(passwd) + 1);
+ strcpy(password, passwd);
+ resp_msg->resp_retcode = 0;
+ resp_msg->resp = password;
+ resp[i] = resp_msg;
+ retval = PAM_SUCCESS;
+ }
+ }
+ return retval;
+}
+
#ifdef __linux__
#include <fcntl.h>
#include <linux/oom.h>
@@ -121,6 +152,8 @@ gethash(void)
}
#endif /* HAVE_SHADOW_H */
+ /* pam, store user name */
+ hash = pw->pw_name;
return hash;
}
@@ -129,11 +162,12 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
const char *hash)
{
XRRScreenChangeNotifyEvent *rre;
- char buf[32], passwd[256], *inputhash;
- int num, screen, running, failure, oldc;
+ char buf[32];
+ int num, screen, running, failure, oldc, retval;
unsigned int len, color;
KeySym ksym;
XEvent ev;
+ pam_handle_t *pamh;
len = 0;
running = 1;
@@ -160,10 +194,26 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
case XK_Return:
passwd[len] = '\0';
errno = 0;
- if (!(inputhash = crypt(passwd, hash)))
- fprintf(stderr, "slock: crypt: %s\n", strerror(errno));
+ retval = pam_start(pam_service, hash, &pamc, &pamh);
+ color = PAM;
+ for (screen = 0; screen < nscreens; screen++) {
+ XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]);
+ XClearWindow(dpy, locks[screen]->win);
+ XRaiseWindow(dpy, locks[screen]->win);
+ }
+ XSync(dpy, False);
+
+ if (retval == PAM_SUCCESS)
+ retval = pam_authenticate(pamh, 0);
+ if (retval == PAM_SUCCESS)
+ retval = pam_acct_mgmt(pamh, 0);
+
+ running = 1;
+ if (retval == PAM_SUCCESS)
+ running = 0;
else
- running = !!strcmp(inputhash, hash);
+ fprintf(stderr, "slock: %s\n", pam_strerror(pamh, retval));
+ pam_end(pamh, retval);
if (running) {
XBell(dpy, 100);
failure = 1;
@@ -339,10 +389,9 @@ main(int argc, char **argv) {
dontkillme();
#endif
+ /* the contents of hash are used to transport the current user name */
hash = gethash();
errno = 0;
- if (!crypt("", hash))
- die("slock: crypt: %s\n", strerror(errno));
if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n");
+63
View File
@@ -0,0 +1,63 @@
diff --git a/config.def.h b/config.def.h
index 9855e21..d01bd38 100644
--- a/config.def.h
+++ b/config.def.h
@@ -10,3 +10,6 @@ static const char *colorname[NUMCOLS] = {
/* treat a cleared input like a wrong password (color) */
static const int failonclear = 1;
+
+/* time in seconds before the monitor shuts down */
+static const int monitortime = 5;
diff --git a/slock.c b/slock.c
index d2f0886..f65a43b 100644
--- a/slock.c
+++ b/slock.c
@@ -15,6 +15,7 @@
#include <unistd.h>
#include <sys/types.h>
#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/dpms.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -306,6 +307,7 @@ main(int argc, char **argv) {
const char *hash;
Display *dpy;
int s, nlocks, nscreens;
+ CARD16 standby, suspend, off;
ARGBEGIN {
case 'v':
@@ -366,6 +368,20 @@ main(int argc, char **argv) {
if (nlocks != nscreens)
return 1;
+ /* DPMS magic to disable the monitor */
+ if (!DPMSCapable(dpy))
+ die("slock: DPMSCapable failed\n");
+ if (!DPMSEnable(dpy))
+ die("slock: DPMSEnable failed\n");
+ if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off))
+ die("slock: DPMSGetTimeouts failed\n");
+ if (!standby || !suspend || !off)
+ die("slock: at least one DPMS variable is zero\n");
+ if (!DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime))
+ die("slock: DPMSSetTimeouts failed\n");
+
+ XSync(dpy, 0);
+
/* run post-lock command */
if (argc > 0) {
switch (fork()) {
@@ -383,5 +399,9 @@ main(int argc, char **argv) {
/* everything is now blank. Wait for the correct password */
readpw(dpy, &rr, locks, nscreens, hash);
+ /* reset DPMS values to inital ones */
+ DPMSSetTimeouts(dpy, standby, suspend, off);
+ XSync(dpy, 0);
+
return 0;
}
+164 -11
View File
@@ -6,7 +6,9 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <grp.h> #include <grp.h>
#include <limits.h>
#include <pwd.h> #include <pwd.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
@@ -16,20 +18,29 @@
#include <spawn.h> #include <spawn.h>
#include <sys/types.h> #include <sys/types.h>
#include <X11/extensions/Xrandr.h> #include <X11/extensions/Xrandr.h>
#include <X11/extensions/dpms.h>
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/XF86keysym.h> #include <X11/XF86keysym.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <Imlib2.h>
#include "arg.h" #include "arg.h"
#include "util.h" #include "util.h"
char *argv0; char *argv0;
static int pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr);
struct pam_conv pamc = {pam_conv, NULL};
char passwd[256];
enum { enum {
INIT, INIT,
INPUT, INPUT,
FAILED, FAILED,
PAM,
NUMCOLS NUMCOLS
}; };
@@ -37,6 +48,7 @@ struct lock {
int screen; int screen;
Window root, win; Window root, win;
Pixmap pmap; Pixmap pmap;
Pixmap bgmap;
unsigned long colors[NUMCOLS]; unsigned long colors[NUMCOLS];
}; };
@@ -48,6 +60,8 @@ struct xrandr {
#include "config.h" #include "config.h"
Imlib_Image image;
static void static void
die(const char *errstr, ...) die(const char *errstr, ...)
{ {
@@ -59,8 +73,32 @@ die(const char *errstr, ...)
exit(1); exit(1);
} }
static int
pam_conv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int retval = PAM_CONV_ERR;
for(int i=0; i<num_msg; i++) {
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF &&
strncmp(msg[i]->msg, "Password: ", 10) == 0) {
struct pam_response *resp_msg = malloc(sizeof(struct pam_response));
if (!resp_msg)
die("malloc failed\n");
char *password = malloc(strlen(passwd) + 1);
if (!password)
die("malloc failed\n");
memset(password, 0, strlen(passwd) + 1);
strcpy(password, passwd);
resp_msg->resp_retcode = 0;
resp_msg->resp = password;
resp[i] = resp_msg;
retval = PAM_SUCCESS;
}
}
return retval;
}
#ifdef __linux__ #ifdef __linux__
#include <fcntl.h>
#include <linux/oom.h> #include <linux/oom.h>
static void static void
@@ -123,6 +161,8 @@ gethash(void)
} }
#endif /* HAVE_SHADOW_H */ #endif /* HAVE_SHADOW_H */
/* pam, store user name */
hash = pw->pw_name;
return hash; return hash;
} }
@@ -131,11 +171,12 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
const char *hash) const char *hash)
{ {
XRRScreenChangeNotifyEvent *rre; XRRScreenChangeNotifyEvent *rre;
char buf[32], passwd[256], *inputhash; char buf[32];
int num, screen, running, failure, oldc; int num, screen, running, failure, oldc, retval;
unsigned int len, color; unsigned int len, color;
KeySym ksym; KeySym ksym;
XEvent ev; XEvent ev;
pam_handle_t *pamh;
len = 0; len = 0;
running = 1; running = 1;
@@ -170,10 +211,26 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
case XK_Return: case XK_Return:
passwd[len] = '\0'; passwd[len] = '\0';
errno = 0; errno = 0;
if (!(inputhash = crypt(passwd, hash))) retval = pam_start(pam_service, hash, &pamc, &pamh);
fprintf(stderr, "slock: crypt: %s\n", strerror(errno)); // color = PAM;
// for (screen = 0; screen < nscreens; screen++) {
// XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]);
// XClearWindow(dpy, locks[screen]->win);
// XRaiseWindow(dpy, locks[screen]->win);
// }
// XSync(dpy, False);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0);
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0);
running = 1;
if (retval == PAM_SUCCESS)
running = 0;
else else
running = !!strcmp(inputhash, hash); fprintf(stderr, "slock: %s\n", pam_strerror(pamh, retval));
pam_end(pamh, retval);
if (running) { if (running) {
XBell(dpy, 100); XBell(dpy, 100);
failure = 1; failure = 1;
@@ -203,9 +260,10 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT);
if (running && oldc != color) { if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) { for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy, if (locks[screen]->bgmap)
locks[screen]->win, XSetWindowBackgroundPixmap(dpy, locks[screen]->win, locks[screen]->bgmap);
locks[screen]->colors[color]); else
XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]);
XClearWindow(dpy, locks[screen]->win); XClearWindow(dpy, locks[screen]->win);
} }
oldc = color; oldc = color;
@@ -248,6 +306,17 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
lock->screen = screen; lock->screen = screen;
lock->root = RootWindow(dpy, lock->screen); lock->root = RootWindow(dpy, lock->screen);
if(image)
{
lock->bgmap = XCreatePixmap(dpy, lock->root, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), DefaultDepth(dpy, lock->screen));
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisual(dpy, lock->screen));
imlib_context_set_colormap(DefaultColormap(dpy, lock->screen));
imlib_context_set_drawable(lock->bgmap);
imlib_render_image_on_drawable(0, 0);
imlib_free_image();
}
for (i = 0; i < NUMCOLS; i++) { for (i = 0; i < NUMCOLS; i++) {
XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen),
colorname[i], &color, &dummy); colorname[i], &color, &dummy);
@@ -264,6 +333,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
CopyFromParent, CopyFromParent,
DefaultVisual(dpy, lock->screen), DefaultVisual(dpy, lock->screen),
CWOverrideRedirect | CWBackPixel, &wa); CWOverrideRedirect | CWBackPixel, &wa);
if(lock->bgmap)
XSetWindowBackgroundPixmap(dpy, lock->win, lock->bgmap);
lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8); lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8);
invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap,
&color, &color, 0, 0); &color, &color, 0, 0);
@@ -310,6 +381,28 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
return NULL; return NULL;
} }
static int
get_xss_sleep_lock_fd(void)
{
char *env_str, *end;
long env_val;
env_str = getenv("XSS_SLEEP_LOCK_FD");
if (!env_str || !*env_str)
return -1;
errno = 0;
env_val = strtol(env_str, &end, 10);
if (errno ||
*end ||
(env_val < 0 || env_val > INT_MAX)) {
fprintf(stderr, "slock: strtol $XSS_SLEEP_LOCK_FD: %s\n",
errno ? strerror(errno) : "invalid value");
return -1;
}
return (int)env_val;
}
static void static void
usage(void) usage(void)
{ {
@@ -327,6 +420,8 @@ main(int argc, char **argv) {
const char *hash; const char *hash;
Display *dpy; Display *dpy;
int s, nlocks, nscreens; int s, nlocks, nscreens;
CARD16 standby, suspend, off;
int lockfd;
ARGBEGIN { ARGBEGIN {
case 'v': case 'v':
@@ -336,6 +431,18 @@ main(int argc, char **argv) {
usage(); usage();
} ARGEND } ARGEND
lockfd = get_xss_sleep_lock_fd();
if (lockfd >= 0) {
int flags = fcntl(lockfd, F_GETFD);
if (flags < 0) {
fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_GETFD: %s\n",
strerror(errno));
} else if (fcntl(lockfd, F_SETFD, flags | FD_CLOEXEC) == -1) {
fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_SETFD: %s\n",
strerror(errno));
}
}
/* validate drop-user and -group */ /* validate drop-user and -group */
errno = 0; errno = 0;
if (!(pwd = getpwnam(user))) if (!(pwd = getpwnam(user)))
@@ -352,10 +459,9 @@ main(int argc, char **argv) {
dontkillme(); dontkillme();
#endif #endif
/* the contents of hash are used to transport the current user name */
hash = gethash(); hash = gethash();
errno = 0; errno = 0;
if (!crypt("", hash))
die("slock: crypt: %s\n", strerror(errno));
if (!(dpy = XOpenDisplay(NULL))) if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n"); die("slock: cannot open display\n");
@@ -368,6 +474,32 @@ main(int argc, char **argv) {
if (setuid(duid) < 0) if (setuid(duid) < 0)
die("slock: setuid: %s\n", strerror(errno)); die("slock: setuid: %s\n", strerror(errno));
/* Load picture */
Imlib_Image buffer = imlib_load_image(background_image);
imlib_context_set_image(buffer);
int background_image_width = imlib_image_get_width();
int background_image_height = imlib_image_get_height();
/* Create an image to be rendered */
Screen *scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
image = imlib_create_image(scr->width, scr->height);
imlib_context_set_image(image);
/* Fill the image for every X monitor */
XRRMonitorInfo *monitors;
int number_of_monitors;
monitors = XRRGetMonitors(dpy, RootWindow(dpy, XScreenNumberOfScreen(scr)), True, &number_of_monitors);
int i;
for (i = 0; i < number_of_monitors; i++) {
imlib_blend_image_onto_image(buffer, 0, 0, 0, background_image_width, background_image_height, monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height);
}
/* Clean up */
imlib_context_set_image(buffer);
imlib_free_image();
imlib_context_set_image(image);
/* check for Xrandr support */ /* check for Xrandr support */
rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
@@ -387,6 +519,23 @@ main(int argc, char **argv) {
if (nlocks != nscreens) if (nlocks != nscreens)
return 1; return 1;
if (lockfd >= 0 && close(lockfd) < 0)
fprintf(stderr, "slock: close $XSS_SLEEP_LOCK_FD: %s\n", strerror(errno));
/* DPMS magic to disable the monitor */
if (!DPMSCapable(dpy))
die("slock: DPMSCapable failed\n");
if (!DPMSEnable(dpy))
die("slock: DPMSEnable failed\n");
if (!DPMSGetTimeouts(dpy, &standby, &suspend, &off))
die("slock: DPMSGetTimeouts failed\n");
if (!standby || !suspend || !off)
die("slock: at least one DPMS variable is zero\n");
if (!DPMSSetTimeouts(dpy, monitortime, monitortime, monitortime))
die("slock: DPMSSetTimeouts failed\n");
XSync(dpy, 0);
/* run post-lock command */ /* run post-lock command */
if (argc > 0) { if (argc > 0) {
pid_t pid; pid_t pid;
@@ -401,5 +550,9 @@ main(int argc, char **argv) {
/* everything is now blank. Wait for the correct password */ /* everything is now blank. Wait for the correct password */
readpw(dpy, &rr, locks, nscreens, hash); readpw(dpy, &rr, locks, nscreens, hash);
/* reset DPMS values to inital ones */
DPMSSetTimeouts(dpy, standby, suspend, off);
XSync(dpy, 0);
return 0; return 0;
} }
+405
View File
@@ -0,0 +1,405 @@
/* See LICENSE file for license details. */
#define _XOPEN_SOURCE 500
#if HAVE_SHADOW_H
#include <shadow.h>
#endif
#include <ctype.h>
#include <errno.h>
#include <grp.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <spawn.h>
#include <sys/types.h>
#include <X11/extensions/Xrandr.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/XF86keysym.h>
#include "arg.h"
#include "util.h"
char *argv0;
enum {
INIT,
INPUT,
FAILED,
NUMCOLS
};
struct lock {
int screen;
Window root, win;
Pixmap pmap;
unsigned long colors[NUMCOLS];
};
struct xrandr {
int active;
int evbase;
int errbase;
};
#include "config.h"
static void
die(const char *errstr, ...)
{
va_list ap;
va_start(ap, errstr);
vfprintf(stderr, errstr, ap);
va_end(ap);
exit(1);
}
#ifdef __linux__
#include <fcntl.h>
#include <linux/oom.h>
static void
dontkillme(void)
{
FILE *f;
const char oomfile[] = "/proc/self/oom_score_adj";
if (!(f = fopen(oomfile, "w"))) {
if (errno == ENOENT)
return;
die("slock: fopen %s: %s\n", oomfile, strerror(errno));
}
fprintf(f, "%d", OOM_SCORE_ADJ_MIN);
if (fclose(f)) {
if (errno == EACCES)
die("slock: unable to disable OOM killer. "
"Make sure to suid or sgid slock.\n");
else
die("slock: fclose %s: %s\n", oomfile, strerror(errno));
}
}
#endif
static const char *
gethash(void)
{
const char *hash;
struct passwd *pw;
/* Check if the current user has a password entry */
errno = 0;
if (!(pw = getpwuid(getuid()))) {
if (errno)
die("slock: getpwuid: %s\n", strerror(errno));
else
die("slock: cannot retrieve password entry\n");
}
hash = pw->pw_passwd;
#if HAVE_SHADOW_H
if (!strcmp(hash, "x")) {
struct spwd *sp;
if (!(sp = getspnam(pw->pw_name)))
die("slock: getspnam: cannot retrieve shadow entry. "
"Make sure to suid or sgid slock.\n");
hash = sp->sp_pwdp;
}
#else
if (!strcmp(hash, "*")) {
#ifdef __OpenBSD__
if (!(pw = getpwuid_shadow(getuid())))
die("slock: getpwnam_shadow: cannot retrieve shadow entry. "
"Make sure to suid or sgid slock.\n");
hash = pw->pw_passwd;
#else
die("slock: getpwuid: cannot retrieve shadow entry. "
"Make sure to suid or sgid slock.\n");
#endif /* __OpenBSD__ */
}
#endif /* HAVE_SHADOW_H */
return hash;
}
static void
readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
const char *hash)
{
XRRScreenChangeNotifyEvent *rre;
char buf[32], passwd[256], *inputhash;
int num, screen, running, failure, oldc;
unsigned int len, color;
KeySym ksym;
XEvent ev;
len = 0;
running = 1;
failure = 0;
oldc = INIT;
while (running && !XNextEvent(dpy, &ev)) {
if (ev.type == KeyPress) {
explicit_bzero(&buf, sizeof(buf));
num = XLookupString(&ev.xkey, buf, sizeof(buf), &ksym, 0);
if (IsKeypadKey(ksym)) {
if (ksym == XK_KP_Enter)
ksym = XK_Return;
else if (ksym >= XK_KP_0 && ksym <= XK_KP_9)
ksym = (ksym - XK_KP_0) + XK_0;
}
if (IsFunctionKey(ksym) ||
IsKeypadKey(ksym) ||
IsMiscFunctionKey(ksym) ||
IsPFKey(ksym) ||
IsPrivateKeypadKey(ksym))
continue;
switch (ksym) {
case XF86XK_AudioMute:
case XF86XK_AudioRaiseVolume:
case XF86XK_AudioLowerVolume:
case XF86XK_AudioMicMute:
case XF86XK_MonBrightnessUp:
case XF86XK_MonBrightnessDown:
XSendEvent(dpy, DefaultRootWindow(dpy), True, KeyPressMask, &ev);
break;
case XK_Return:
passwd[len] = '\0';
errno = 0;
if (!(inputhash = crypt(passwd, hash)))
fprintf(stderr, "slock: crypt: %s\n", strerror(errno));
else
running = !!strcmp(inputhash, hash);
if (running) {
XBell(dpy, 100);
failure = 1;
}
explicit_bzero(&passwd, sizeof(passwd));
len = 0;
break;
case XK_Escape:
explicit_bzero(&passwd, sizeof(passwd));
len = 0;
break;
case XK_BackSpace:
if (len)
passwd[--len] = '\0';
break;
default:
if (num && !iscntrl((int)buf[0]) &&
(len + num < sizeof(passwd))) {
memcpy(passwd + len, buf, num);
len += num;
} else if (buf[0] == '\025') { /* ctrl-u clears input */
explicit_bzero(&passwd, sizeof(passwd));
len = 0;
}
break;
}
color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT);
if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy,
locks[screen]->win,
locks[screen]->colors[color]);
XClearWindow(dpy, locks[screen]->win);
}
oldc = color;
}
} else if (rr->active && ev.type == rr->evbase + RRScreenChangeNotify) {
rre = (XRRScreenChangeNotifyEvent*)&ev;
for (screen = 0; screen < nscreens; screen++) {
if (locks[screen]->win == rre->window) {
if (rre->rotation == RR_Rotate_90 ||
rre->rotation == RR_Rotate_270)
XResizeWindow(dpy, locks[screen]->win,
rre->height, rre->width);
else
XResizeWindow(dpy, locks[screen]->win,
rre->width, rre->height);
XClearWindow(dpy, locks[screen]->win);
break;
}
}
} else {
for (screen = 0; screen < nscreens; screen++)
XRaiseWindow(dpy, locks[screen]->win);
}
}
}
static struct lock *
lockscreen(Display *dpy, struct xrandr *rr, int screen)
{
char curs[] = {0, 0, 0, 0, 0, 0, 0, 0};
int i, ptgrab, kbgrab;
struct lock *lock;
XColor color, dummy;
XSetWindowAttributes wa;
Cursor invisible;
if (dpy == NULL || screen < 0 || !(lock = malloc(sizeof(struct lock))))
return NULL;
lock->screen = screen;
lock->root = RootWindow(dpy, lock->screen);
for (i = 0; i < NUMCOLS; i++) {
XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen),
colorname[i], &color, &dummy);
lock->colors[i] = color.pixel;
}
/* init */
wa.override_redirect = 1;
wa.background_pixel = lock->colors[INIT];
lock->win = XCreateWindow(dpy, lock->root, 0, 0,
DisplayWidth(dpy, lock->screen),
DisplayHeight(dpy, lock->screen),
0, DefaultDepth(dpy, lock->screen),
CopyFromParent,
DefaultVisual(dpy, lock->screen),
CWOverrideRedirect | CWBackPixel, &wa);
lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8);
invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap,
&color, &color, 0, 0);
XDefineCursor(dpy, lock->win, invisible);
/* Try to grab mouse pointer *and* keyboard for 600ms, else fail the lock */
for (i = 0, ptgrab = kbgrab = -1; i < 6; i++) {
if (ptgrab != GrabSuccess) {
ptgrab = XGrabPointer(dpy, lock->root, False,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask, GrabModeAsync,
GrabModeAsync, None, invisible, CurrentTime);
}
if (kbgrab != GrabSuccess) {
kbgrab = XGrabKeyboard(dpy, lock->root, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
}
/* input is grabbed: we can lock the screen */
if (ptgrab == GrabSuccess && kbgrab == GrabSuccess) {
XMapRaised(dpy, lock->win);
if (rr->active)
XRRSelectInput(dpy, lock->win, RRScreenChangeNotifyMask);
XSelectInput(dpy, lock->root, SubstructureNotifyMask);
return lock;
}
/* retry on AlreadyGrabbed but fail on other errors */
if ((ptgrab != AlreadyGrabbed && ptgrab != GrabSuccess) ||
(kbgrab != AlreadyGrabbed && kbgrab != GrabSuccess))
break;
usleep(100000);
}
/* we couldn't grab all input: fail out */
if (ptgrab != GrabSuccess)
fprintf(stderr, "slock: unable to grab mouse pointer for screen %d\n",
screen);
if (kbgrab != GrabSuccess)
fprintf(stderr, "slock: unable to grab keyboard for screen %d\n",
screen);
return NULL;
}
static void
usage(void)
{
die("usage: slock [-v] [cmd [arg ...]]\n");
}
int
main(int argc, char **argv) {
struct xrandr rr;
struct lock **locks;
struct passwd *pwd;
struct group *grp;
uid_t duid;
gid_t dgid;
const char *hash;
Display *dpy;
int s, nlocks, nscreens;
ARGBEGIN {
case 'v':
puts("slock-"VERSION);
return 0;
default:
usage();
} ARGEND
/* validate drop-user and -group */
errno = 0;
if (!(pwd = getpwnam(user)))
die("slock: getpwnam %s: %s\n", user,
errno ? strerror(errno) : "user entry not found");
duid = pwd->pw_uid;
errno = 0;
if (!(grp = getgrnam(group)))
die("slock: getgrnam %s: %s\n", group,
errno ? strerror(errno) : "group entry not found");
dgid = grp->gr_gid;
#ifdef __linux__
dontkillme();
#endif
hash = gethash();
errno = 0;
if (!crypt("", hash))
die("slock: crypt: %s\n", strerror(errno));
if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n");
/* drop privileges */
if (setgroups(0, NULL) < 0)
die("slock: setgroups: %s\n", strerror(errno));
if (setgid(dgid) < 0)
die("slock: setgid: %s\n", strerror(errno));
if (setuid(duid) < 0)
die("slock: setuid: %s\n", strerror(errno));
/* check for Xrandr support */
rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
/* get number of screens in display "dpy" and blank them */
nscreens = ScreenCount(dpy);
if (!(locks = calloc(nscreens, sizeof(struct lock *))))
die("slock: out of memory\n");
for (nlocks = 0, s = 0; s < nscreens; s++) {
if ((locks[s] = lockscreen(dpy, &rr, s)) != NULL)
nlocks++;
else
break;
}
XSync(dpy, 0);
/* did we manage to lock everything? */
if (nlocks != nscreens)
return 1;
/* run post-lock command */
if (argc > 0) {
pid_t pid;
extern char **environ;
int err = posix_spawnp(&pid, argv[0], NULL, NULL, argv, environ);
if (err) {
die("slock: failed to execute post-lock command: %s: %s\n",
argv[0], strerror(err));
}
}
/* everything is now blank. Wait for the correct password */
readpw(dpy, &rr, locks, nscreens, hash);
return 0;
}
+153 -11
View File
@@ -6,7 +6,9 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h>
#include <grp.h> #include <grp.h>
#include <limits.h>
#include <pwd.h> #include <pwd.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdlib.h> #include <stdlib.h>
@@ -19,16 +21,25 @@
#include <X11/keysym.h> #include <X11/keysym.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/XF86keysym.h>
#include <security/pam_appl.h>
#include <security/pam_misc.h>
#include <Imlib2.h>
#include "arg.h" #include "arg.h"
#include "util.h" #include "util.h"
char *argv0; char *argv0;
static int pam_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr);
struct pam_conv pamc = {pam_conv, NULL};
char passwd[256];
enum { enum {
INIT, INIT,
INPUT, INPUT,
FAILED, FAILED,
PAM,
NUMCOLS NUMCOLS
}; };
@@ -36,6 +47,7 @@ struct lock {
int screen; int screen;
Window root, win; Window root, win;
Pixmap pmap; Pixmap pmap;
Pixmap bgmap;
unsigned long colors[NUMCOLS]; unsigned long colors[NUMCOLS];
}; };
@@ -47,6 +59,8 @@ struct xrandr {
#include "config.h" #include "config.h"
Imlib_Image image;
static void static void
die(const char *errstr, ...) die(const char *errstr, ...)
{ {
@@ -58,8 +72,32 @@ die(const char *errstr, ...)
exit(1); exit(1);
} }
static int
pam_conv(int num_msg, const struct pam_message **msg,
struct pam_response **resp, void *appdata_ptr)
{
int retval = PAM_CONV_ERR;
for(int i=0; i<num_msg; i++) {
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF &&
strncmp(msg[i]->msg, "Password: ", 10) == 0) {
struct pam_response *resp_msg = malloc(sizeof(struct pam_response));
if (!resp_msg)
die("malloc failed\n");
char *password = malloc(strlen(passwd) + 1);
if (!password)
die("malloc failed\n");
memset(password, 0, strlen(passwd) + 1);
strcpy(password, passwd);
resp_msg->resp_retcode = 0;
resp_msg->resp = password;
resp[i] = resp_msg;
retval = PAM_SUCCESS;
}
}
return retval;
}
#ifdef __linux__ #ifdef __linux__
#include <fcntl.h>
#include <linux/oom.h> #include <linux/oom.h>
static void static void
@@ -122,6 +160,8 @@ gethash(void)
} }
#endif /* HAVE_SHADOW_H */ #endif /* HAVE_SHADOW_H */
/* pam, store user name */
hash = pw->pw_name;
return hash; return hash;
} }
@@ -130,11 +170,12 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
const char *hash) const char *hash)
{ {
XRRScreenChangeNotifyEvent *rre; XRRScreenChangeNotifyEvent *rre;
char buf[32], passwd[256], *inputhash; char buf[32];
int num, screen, running, failure, oldc; int num, screen, running, failure, oldc, retval;
unsigned int len, color; unsigned int len, color;
KeySym ksym; KeySym ksym;
XEvent ev; XEvent ev;
pam_handle_t *pamh;
len = 0; len = 0;
running = 1; running = 1;
@@ -158,13 +199,37 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
IsPrivateKeypadKey(ksym)) IsPrivateKeypadKey(ksym))
continue; continue;
switch (ksym) { switch (ksym) {
case XF86XK_AudioMute:
case XF86XK_AudioRaiseVolume:
case XF86XK_AudioLowerVolume:
case XF86XK_AudioMicMute:
case XF86XK_MonBrightnessUp:
case XF86XK_MonBrightnessDown:
XSendEvent(dpy, DefaultRootWindow(dpy), True, KeyPressMask, &ev);
break;
case XK_Return: case XK_Return:
passwd[len] = '\0'; passwd[len] = '\0';
errno = 0; errno = 0;
if (!(inputhash = crypt(passwd, hash))) retval = pam_start(pam_service, hash, &pamc, &pamh);
fprintf(stderr, "slock: crypt: %s\n", strerror(errno)); color = PAM;
for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[color]);
XClearWindow(dpy, locks[screen]->win);
XRaiseWindow(dpy, locks[screen]->win);
}
XSync(dpy, False);
if (retval == PAM_SUCCESS)
retval = pam_authenticate(pamh, 0);
if (retval == PAM_SUCCESS)
retval = pam_acct_mgmt(pamh, 0);
running = 1;
if (retval == PAM_SUCCESS)
running = 0;
else else
running = !!strcmp(inputhash, hash); fprintf(stderr, "slock: %s\n", pam_strerror(pamh, retval));
pam_end(pamh, retval);
if (running) { if (running) {
XBell(dpy, 100); XBell(dpy, 100);
failure = 1; failure = 1;
@@ -194,9 +259,10 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens,
color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT); color = len ? INPUT : ((failure || failonclear) ? FAILED : INIT);
if (running && oldc != color) { if (running && oldc != color) {
for (screen = 0; screen < nscreens; screen++) { for (screen = 0; screen < nscreens; screen++) {
XSetWindowBackground(dpy, if (locks[screen]->bgmap)
locks[screen]->win, XSetWindowBackgroundPixmap(dpy, locks[screen]->win, locks[screen]->bgmap);
locks[screen]->colors[color]); else
XSetWindowBackground(dpy, locks[screen]->win, locks[screen]->colors[0]);
XClearWindow(dpy, locks[screen]->win); XClearWindow(dpy, locks[screen]->win);
} }
oldc = color; oldc = color;
@@ -239,6 +305,17 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
lock->screen = screen; lock->screen = screen;
lock->root = RootWindow(dpy, lock->screen); lock->root = RootWindow(dpy, lock->screen);
if(image)
{
lock->bgmap = XCreatePixmap(dpy, lock->root, DisplayWidth(dpy, lock->screen), DisplayHeight(dpy, lock->screen), DefaultDepth(dpy, lock->screen));
imlib_context_set_display(dpy);
imlib_context_set_visual(DefaultVisual(dpy, lock->screen));
imlib_context_set_colormap(DefaultColormap(dpy, lock->screen));
imlib_context_set_drawable(lock->bgmap);
imlib_render_image_on_drawable(0, 0);
imlib_free_image();
}
for (i = 0; i < NUMCOLS; i++) { for (i = 0; i < NUMCOLS; i++) {
XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen), XAllocNamedColor(dpy, DefaultColormap(dpy, lock->screen),
colorname[i], &color, &dummy); colorname[i], &color, &dummy);
@@ -255,6 +332,8 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
CopyFromParent, CopyFromParent,
DefaultVisual(dpy, lock->screen), DefaultVisual(dpy, lock->screen),
CWOverrideRedirect | CWBackPixel, &wa); CWOverrideRedirect | CWBackPixel, &wa);
if(lock->bgmap)
XSetWindowBackgroundPixmap(dpy, lock->win, lock->bgmap);
lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8); lock->pmap = XCreateBitmapFromData(dpy, lock->win, curs, 8, 8);
invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap, invisible = XCreatePixmapCursor(dpy, lock->pmap, lock->pmap,
&color, &color, 0, 0); &color, &color, 0, 0);
@@ -301,6 +380,28 @@ lockscreen(Display *dpy, struct xrandr *rr, int screen)
return NULL; return NULL;
} }
static int
get_xss_sleep_lock_fd(void)
{
char *env_str, *end;
long env_val;
env_str = getenv("XSS_SLEEP_LOCK_FD");
if (!env_str || !*env_str)
return -1;
errno = 0;
env_val = strtol(env_str, &end, 10);
if (errno ||
*end ||
(env_val < 0 || env_val > INT_MAX)) {
fprintf(stderr, "slock: strtol $XSS_SLEEP_LOCK_FD: %s\n",
errno ? strerror(errno) : "invalid value");
return -1;
}
return (int)env_val;
}
static void static void
usage(void) usage(void)
{ {
@@ -318,6 +419,7 @@ main(int argc, char **argv) {
const char *hash; const char *hash;
Display *dpy; Display *dpy;
int s, nlocks, nscreens; int s, nlocks, nscreens;
int lockfd;
ARGBEGIN { ARGBEGIN {
case 'v': case 'v':
@@ -327,6 +429,18 @@ main(int argc, char **argv) {
usage(); usage();
} ARGEND } ARGEND
lockfd = get_xss_sleep_lock_fd();
if (lockfd >= 0) {
int flags = fcntl(lockfd, F_GETFD);
if (flags < 0) {
fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_GETFD: %s\n",
strerror(errno));
} else if (fcntl(lockfd, F_SETFD, flags | FD_CLOEXEC) == -1) {
fprintf(stderr, "slock: fcntl $XSS_SLEEP_LOCK_FD F_SETFD: %s\n",
strerror(errno));
}
}
/* validate drop-user and -group */ /* validate drop-user and -group */
errno = 0; errno = 0;
if (!(pwd = getpwnam(user))) if (!(pwd = getpwnam(user)))
@@ -343,10 +457,9 @@ main(int argc, char **argv) {
dontkillme(); dontkillme();
#endif #endif
/* the contents of hash are used to transport the current user name */
hash = gethash(); hash = gethash();
errno = 0; errno = 0;
if (!crypt("", hash))
die("slock: crypt: %s\n", strerror(errno));
if (!(dpy = XOpenDisplay(NULL))) if (!(dpy = XOpenDisplay(NULL)))
die("slock: cannot open display\n"); die("slock: cannot open display\n");
@@ -359,6 +472,32 @@ main(int argc, char **argv) {
if (setuid(duid) < 0) if (setuid(duid) < 0)
die("slock: setuid: %s\n", strerror(errno)); die("slock: setuid: %s\n", strerror(errno));
/* Load picture */
Imlib_Image buffer = imlib_load_image(background_image);
imlib_context_set_image(buffer);
int background_image_width = imlib_image_get_width();
int background_image_height = imlib_image_get_height();
/* Create an image to be rendered */
Screen *scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
image = imlib_create_image(scr->width, scr->height);
imlib_context_set_image(image);
/* Fill the image for every X monitor */
XRRMonitorInfo *monitors;
int number_of_monitors;
monitors = XRRGetMonitors(dpy, RootWindow(dpy, XScreenNumberOfScreen(scr)), True, &number_of_monitors);
int i;
for (i = 0; i < number_of_monitors; i++) {
imlib_blend_image_onto_image(buffer, 0, 0, 0, background_image_width, background_image_height, monitors[i].x, monitors[i].y, monitors[i].width, monitors[i].height);
}
/* Clean up */
imlib_context_set_image(buffer);
imlib_free_image();
imlib_context_set_image(image);
/* check for Xrandr support */ /* check for Xrandr support */
rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase); rr.active = XRRQueryExtension(dpy, &rr.evbase, &rr.errbase);
@@ -378,6 +517,9 @@ main(int argc, char **argv) {
if (nlocks != nscreens) if (nlocks != nscreens)
return 1; return 1;
if (lockfd >= 0 && close(lockfd) < 0)
fprintf(stderr, "slock: close $XSS_SLEEP_LOCK_FD: %s\n", strerror(errno));
/* run post-lock command */ /* run post-lock command */
if (argc > 0) { if (argc > 0) {
pid_t pid; pid_t pid;
+8 -9
View File
@@ -1,11 +1,10 @@
--- slock.c --- slock.c
+++ slock.c +++ slock.c
@@ -186,7 +186,7 @@ readpw(Display *dpy, struct xrandr *rr, struct lock **locks, int nscreens, @@ -307,6 +308,7 @@ main(int argc, char **argv) {
case XF86XK_AudioStop: const char *hash;
case XF86XK_AudioPrev: Display *dpy;
case XF86XK_AudioNext: int s, nlocks, nscreens;
- XSendEvent(dpy, locks[0]->root, True, KeyPressMask, &ev); + CARD16 standby, suspend, off;
+ XSendEvent(dpy, DefaultRootWindow(dpy), True, KeyPressMask, &ev);
break; ARGBEGIN {
case XK_Return: case 'v':
passwd[len] = '\0';