parent
							
								
									4879d40695
								
							
						
					
					
						commit
						3fca8b8d22
					
				| @ -1,66 +0,0 @@ | ||||
| # swaylock(1) completion | ||||
| 
 | ||||
| _swaylock() | ||||
| { | ||||
|   local cur prev | ||||
|   _get_comp_words_by_ref -n : cur prev | ||||
| 
 | ||||
|   short=( | ||||
|     -h | ||||
|     -c | ||||
|     -s | ||||
|     -t | ||||
|     -v | ||||
|     -i | ||||
|     -u | ||||
|     -f | ||||
|   ) | ||||
| 
 | ||||
|   long=( | ||||
|     --help | ||||
|     --color | ||||
|     --scaling | ||||
|     --tiling | ||||
|     --version | ||||
|     --image | ||||
|     --no-unlock-indicator | ||||
|     --daemonize | ||||
|   ) | ||||
| 
 | ||||
|   scaling=( | ||||
|     'stretch' | ||||
|     'fill' | ||||
|     'fit' | ||||
|     'center' | ||||
|     'tile' | ||||
|   ) | ||||
| 
 | ||||
|   case $prev in | ||||
|     -c|--color) | ||||
|       return | ||||
|       ;; | ||||
|     --scaling) | ||||
|       COMPREPLY=($(compgen -W "${scaling[*]}" -- "$cur")) | ||||
|       return | ||||
|       ;; | ||||
|     -i|--image) | ||||
|       if grep -q : <<< "$cur"; then | ||||
|         output="${cur%%:*}:" | ||||
|         cur="${cur#*:}" | ||||
|       else | ||||
|         output= | ||||
|       fi | ||||
|       COMPREPLY=($(compgen -f -- "$cur")) | ||||
|       return | ||||
|       ;; | ||||
|   esac | ||||
| 
 | ||||
|   if [[ $cur == --* ]]; then | ||||
|     COMPREPLY=($(compgen -W "${long[*]}" -- "$cur")) | ||||
|   else | ||||
|     COMPREPLY=($(compgen -W "${short[*]}" -- "$cur")) | ||||
|     COMPREPLY+=($(compgen -W "${long[*]}" -- "$cur")) | ||||
|   fi | ||||
| 
 | ||||
| } && | ||||
| complete -F _swaylock swaylock | ||||
| @ -1,39 +0,0 @@ | ||||
| # swaylock(1) completion | ||||
| 
 | ||||
| complete -c swaylock -s C -l config --description 'The config file to use. Default: $HOME/.swaylock/config, $XDG_CONFIG_HOME/swaylock/config, and SYSCONFDIR/swaylock/config.' | ||||
| complete -c swaylock -s h -l help --description "Show help message and quit." | ||||
| complete -c swaylock -s f -l daemonize --description "Fork into the background after spawning. Note: this is the default bahavior of i3lock." | ||||
| complete -c swaylock -s v -l version --description "Show the version number and quit." | ||||
| complete -c swaylock -s s -l socket --description "Use the specified socket path. Otherwise, swaymsg will as sway where the socket is (which is the value of $SWAYSOCK, then of $I350CK)." | ||||
| complete -c swaylock -s e -l ignore-empty-password --description 'When an empty password is provided by the user, do not validate it.' | ||||
| 
 | ||||
| # Appearance | ||||
| complete -c swaylock -s u -l no-unlock-indicator --description "Disable the unlock indicator." | ||||
| complete -c swaylock -s i -l image --description "Display the given image, optionally on the given output. Use -c to set a background color." | ||||
| complete -c swaylock -s s -l scaling --description "Scaling mode for images: stretch, fill, fit, center, or tile." | ||||
| complete -c swaylock -s t -l tiling --description "Same as --scaling=tile." | ||||
| complete -c swaylock -s c -l color --description "Turn the screen into the given color. If -i is used, this sets the background of the image into the given color. Defaults to white (ffffff), or transparent (00000000) if an image is in use." | ||||
| complete -c swaylock -l bs-hl-color --description 'Sets the color of backspace highlight segments.' | ||||
| complete -c swaylock -l font --description 'Sets the font of the text inside the indicator.' | ||||
| complete -c swaylock -l indicator-radius --description 'Sets the radius of the indicator to radius pixels. Default: 50' | ||||
| complete -c swaylock -l indicator-thickness --description 'Sets the thickness of the indicator to thickness pixels. Default: 10' | ||||
| complete -c swaylock -l inside-color --description 'Sets the color of the inside of the indicator when typing or idle.' | ||||
| complete -c swaylock -l inside-clear-color --description 'Sets the color of the inside of the indicator when cleared.' | ||||
| complete -c swaylock -l inside-ver-color --description 'Sets the color of the inside of the indicator when verifying.' | ||||
| complete -c swaylock -l inside-wrong-color --description 'Sets the color of the inside of the indicator when invalid.' | ||||
| complete -c swaylock -l key-hl-color --description 'Sets the color of key press highlight segments.' | ||||
| complete -c swaylock -l line-color --description 'Sets the color of the lines that separate the inside and outside of the indicator when typing or idle.' | ||||
| complete -c swaylock -l line-clear-color --description 'Sets the color of the lines that separate the inside and outside of the indicator when cleared.' | ||||
| complete -c swaylock -l line-ver-color --description 'Sets the color of the lines that separate the inside and outside of the indicator when verifying.' | ||||
| complete -c swaylock -l line-wrong-color --description 'Sets the color of the lines that separate the inside and outside of the indicator when invalid.' | ||||
| complete -c swaylock -s n -l line-uses-inside --description 'Use the color of the inside of the indicator for the line separating the inside and outside of the indicator.' | ||||
| complete -c swaylock -s r -l line-uses-ring --description 'Use the outer ring\'s color for the line separating the inside and outside of the indicator.' | ||||
| complete -c swaylock -l ring-color --description 'Sets the color of the outside of the indicator when typing or idle.' | ||||
| complete -c swaylock -l ring-clear-color --description 'Sets the color of the outside of the indicator when cleared.' | ||||
| complete -c swaylock -l ring-ver-color --description 'Sets the color of the outside of the indicator when verifying.' | ||||
| complete -c swaylock -l ring-wrong-color --description 'Sets the color of the outside of the indicator when invalid.' | ||||
| complete -c swaylock -l separator-color --description 'Sets the color of the lines that separate highlight segments.' | ||||
| complete -c swaylock -l text-color --description 'Sets the color of the text inside the indicator when typing or idle.' | ||||
| complete -c swaylock -l text-clear-color --description 'Sets the color of the text inside the indicator when cleared.' | ||||
| complete -c swaylock -l text-ver-color --description 'Sets the color of the text inside the indicator when verifying.' | ||||
| complete -c swaylock -l text-wrong-color --description 'Sets the color of the text inside the indicator when invalid.' | ||||
| @ -1,40 +0,0 @@ | ||||
| #compdef swaylock | ||||
| # | ||||
| # Completion script for swaylock | ||||
| # | ||||
| 
 | ||||
| _arguments -s \ | ||||
|     '(-C --config)'{-C,--config}'[Path to the config file]:filename:_files' \ | ||||
| 	'(-c --color)'{-c,--color}'[Turn the screen into the given color instead of white]:color:' \ | ||||
| 	'(-e --ignore-empty-password)'{-e,--ignore-empty-password}'[When an empty password is provided, do not validate it]' \ | ||||
| 	'(-f --daemonize)'{-f,--daemonize}'[Detach from the controlling terminal after locking]' \ | ||||
| 	'(-h --help)'{-h,--help}'[Show help message and quit]' \ | ||||
|     '(-i --image)'{-i,--image}'[Display an image]:filename:_files' \ | ||||
| 	'(-s --scaling)'{-s,--scaling}'[Scaling mode]:mode:(stretch fill fit center tile)' \ | ||||
| 	'(-t --tiling)'{-t,--tiling}'[Same as --scaling=tile]' \ | ||||
|     '(-u --no-unlock-indicator)'{-u,--no-unlock-indicator}'[Disable the unlock indicator]' \ | ||||
| 	'(-v --version)'{-v,--version}'[Show the version number and quit]' \ | ||||
| 	'(--bs-hl-color)'--bs-hl-color'[Sets the color of backspace highlights segments]:color:' \ | ||||
| 	'(--font)'--font'[Sets the font of the text]:font:' \ | ||||
| 	'(--indicator-radius)'--indicator-radius'[Sets the indicator radius]:radius:' \ | ||||
| 	'(--indicator-thickness)'--indicator-thickness'[Sets the indicator thickness]:thickness:' \ | ||||
| 	'(--inside-color)'--inside-color'[Sets the color of the inside of the indicator]:color:' \ | ||||
| 	'(--inside-clear-color)'--inside-clear-color'[Sets the color of the inside of the indicator when cleared]:color:' \ | ||||
| 	'(--inside-clear-color)'--inside-clear-color'[Sets the color of the inside of the indicator when verifying]:color:' \ | ||||
| 	'(--inside-wrong-color)'--inside-wrong-color'[Sets the color of the inside of the indicator when invalid]:color:' \ | ||||
| 	'(--key-hl-color)'--key-hl-color'[Sets the color of the key press highlight segments]:color:' \ | ||||
| 	'(--line-color)'--line-color'[Sets the color of the line between the inside and ring]:color:' \ | ||||
| 	'(--line-clear-color)'--line-clear-color'[Sets the color of the line between the inside and ring when cleared]:color:' \ | ||||
| 	'(--line-ver-color)'--line-ver-color'[Sets the color of the line between the inside and ring when verifying]:color:' \ | ||||
| 	'(--line-wrong-color)'--line-wrong-color'[Sets the color of the line between the inside and ring when invalid]:color:' \ | ||||
| 	'(-n --line-uses-inside)'{-n,--line-uses-inside}'[Use the inside color for the line between the inside and ring]' \ | ||||
| 	'(-r --line-uses-ring)'{-r,--line--uses-ring}'[Use the ring color for the line between the inside and ring]' \ | ||||
| 	'(--ring-color)'--ring-color'[Sets the color of the ring of the indicator]:color:' \ | ||||
| 	'(--ring-clear-color)'--ring-clear-color'[Sets the color of the ring of the indicator when cleared]:color:' \ | ||||
| 	'(--ring-ver-color)'--ring-ver-color'[Sets the color of the ring of the indicator when verifying]:color:' \ | ||||
| 	'(--ring-wrong-color)'--ring-wrong-color'[Sets the color of the ring of the indicator when invalid]:color:' \ | ||||
| 	'(--separator-color)'--separator-color'[Sets the color of the lines that separate highlight segments]:color:' \ | ||||
| 	'(--text-color)'--text-color'[Sets the color of the text]:color:' \ | ||||
| 	'(--text-clear-color)'--text-clear-color'[Sets the color of the text when cleared]:color:' \ | ||||
| 	'(--text-ver-color)'--text-ver-color'[Sets the color of the text when verifying]:color:' \ | ||||
| 	'(--text-wrong-color)'--text-wrong-color'[Sets the color of the text when invalid]:color:' | ||||
											
												
													File diff suppressed because it is too large
													Load Diff
												
											
										
									
								| @ -1,55 +0,0 @@ | ||||
| sysconfdir = get_option('sysconfdir') | ||||
| 
 | ||||
| dependencies = [ | ||||
|     cairo, | ||||
|     client_protos, | ||||
|     gdk_pixbuf, | ||||
|     math, | ||||
|     pango, | ||||
|     pangocairo, | ||||
|     xkbcommon, | ||||
|     wayland_client, | ||||
|     wlroots, | ||||
| ] | ||||
| 
 | ||||
| sources = [ | ||||
|     'main.c', | ||||
|     'password.c', | ||||
|     'render.c', | ||||
|     'seat.c' | ||||
| ] | ||||
| 
 | ||||
| if libpam.found() | ||||
|     sources += ['pam.c'] | ||||
|     dependencies += [libpam] | ||||
| else | ||||
|     warning('The swaylock binary must be setuid when compiled without libpam') | ||||
|     warning('You must do this manually post-install: chmod a+s /path/to/swaylock') | ||||
|     sources += ['shadow.c'] | ||||
|     if crypt.found() | ||||
|         dependencies += [crypt] | ||||
|     endif | ||||
| endif | ||||
| 
 | ||||
| executable('swaylock', | ||||
|     sources, | ||||
| 	include_directories: [sway_inc], | ||||
| 	dependencies: dependencies, | ||||
| 	link_with: [lib_sway_common, lib_sway_client], | ||||
| 	install_rpath : rpathdir, | ||||
| 	install: true | ||||
| ) | ||||
| 
 | ||||
| if is_freebsd | ||||
| 	install_data( | ||||
| 		'pam/swaylock.freebsd', | ||||
| 		install_dir: sysconfdir + '/pam.d/', | ||||
| 		rename: 'swaylock' | ||||
| 	) | ||||
| else | ||||
| 	install_data( | ||||
| 		'pam/swaylock.linux', | ||||
| 		install_dir: sysconfdir + '/pam.d/', | ||||
| 		rename: 'swaylock' | ||||
| 	) | ||||
| endif | ||||
| @ -1,62 +0,0 @@ | ||||
| #define _POSIX_C_SOURCE 200809L | ||||
| #include <pwd.h> | ||||
| #include <security/pam_appl.h> | ||||
| #include <stdbool.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include "swaylock/swaylock.h" | ||||
| 
 | ||||
| void initialize_pw_backend(void) { | ||||
| 	// TODO: only call pam_start once. keep the same handle the whole time
 | ||||
| } | ||||
| 
 | ||||
| static int function_conversation(int num_msg, const struct pam_message **msg, | ||||
| 		struct pam_response **resp, void *data) { | ||||
| 	struct swaylock_password *pw = data; | ||||
| 	/* PAM expects an array of responses, one for each message */ | ||||
| 	struct pam_response *pam_reply = calloc( | ||||
| 			num_msg, sizeof(struct pam_response)); | ||||
| 	*resp = pam_reply; | ||||
| 	for (int i = 0; i < num_msg; ++i) { | ||||
| 		switch (msg[i]->msg_style) { | ||||
| 		case PAM_PROMPT_ECHO_OFF: | ||||
| 		case PAM_PROMPT_ECHO_ON: | ||||
| 			pam_reply[i].resp = strdup(pw->buffer); // PAM clears and frees this
 | ||||
| 			break; | ||||
| 		case PAM_ERROR_MSG: | ||||
| 		case PAM_TEXT_INFO: | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	return PAM_SUCCESS; | ||||
| } | ||||
| 
 | ||||
| bool attempt_password(struct swaylock_password *pw) { | ||||
| 	struct passwd *passwd = getpwuid(getuid()); | ||||
| 	char *username = passwd->pw_name; | ||||
| 	const struct pam_conv local_conversation = { | ||||
| 		function_conversation, pw | ||||
| 	}; | ||||
| 	pam_handle_t *local_auth_handle = NULL; | ||||
| 	int pam_err; | ||||
| 	if ((pam_err = pam_start("swaylock", username, | ||||
| 					&local_conversation, &local_auth_handle)) != PAM_SUCCESS) { | ||||
| 		wlr_log(WLR_ERROR, "PAM returned error %d", pam_err); | ||||
| 	} | ||||
| 	if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) { | ||||
| 		wlr_log(WLR_ERROR, "pam_authenticate failed"); | ||||
| 		goto fail; | ||||
| 	} | ||||
| 	// TODO: only call pam_end once we succeed at authing. refresh tokens beforehand
 | ||||
| 	if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) { | ||||
| 		wlr_log(WLR_ERROR, "pam_end failed"); | ||||
| 		goto fail; | ||||
| 	} | ||||
| 	clear_password_buffer(pw); | ||||
| 	return true; | ||||
| fail: | ||||
| 	clear_password_buffer(pw); | ||||
| 	return false; | ||||
| } | ||||
| @ -1,6 +0,0 @@ | ||||
| # | ||||
| # PAM configuration file for the swaylock screen locker. By default, it includes | ||||
| # the 'passwd' configuration file (see /etc/pam.d/passwd) | ||||
| # | ||||
| 
 | ||||
| auth include passwd | ||||
| @ -1,6 +0,0 @@ | ||||
| # | ||||
| # PAM configuration file for the swaylock screen locker. By default, it includes | ||||
| # the 'login' configuration file (see /etc/pam.d/login) | ||||
| # | ||||
| 
 | ||||
| auth include login | ||||
| @ -1,190 +0,0 @@ | ||||
| #include <assert.h> | ||||
| #include <errno.h> | ||||
| #include <pwd.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <unistd.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include <xkbcommon/xkbcommon.h> | ||||
| #include "swaylock/swaylock.h" | ||||
| #include "swaylock/seat.h" | ||||
| #include "loop.h" | ||||
| #include "unicode.h" | ||||
| 
 | ||||
| void clear_password_buffer(struct swaylock_password *pw) { | ||||
| 	// Use volatile keyword so so compiler can't optimize this out.
 | ||||
| 	volatile char *buffer = pw->buffer; | ||||
| 	volatile char zero = '\0'; | ||||
| 	for (size_t i = 0; i < sizeof(pw->buffer); ++i) { | ||||
| 		buffer[i] = zero; | ||||
| 	} | ||||
| 	pw->len = 0; | ||||
| } | ||||
| 
 | ||||
| static bool backspace(struct swaylock_password *pw) { | ||||
| 	if (pw->len != 0) { | ||||
| 		pw->buffer[--pw->len] = 0; | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| static void append_ch(struct swaylock_password *pw, uint32_t codepoint) { | ||||
| 	size_t utf8_size = utf8_chsize(codepoint); | ||||
| 	if (pw->len + utf8_size + 1 >= sizeof(pw->buffer)) { | ||||
| 		// TODO: Display error
 | ||||
| 		return; | ||||
| 	} | ||||
| 	utf8_encode(&pw->buffer[pw->len], codepoint); | ||||
| 	pw->buffer[pw->len + utf8_size] = 0; | ||||
| 	pw->len += utf8_size; | ||||
| } | ||||
| 
 | ||||
| static void clear_indicator(void *data) { | ||||
| 	struct swaylock_state *state = data; | ||||
| 	state->clear_indicator_timer = NULL; | ||||
| 	state->auth_state = AUTH_STATE_IDLE; | ||||
| 	damage_state(state); | ||||
| } | ||||
| 
 | ||||
| static void schedule_indicator_clear(struct swaylock_state *state) { | ||||
| 	if (state->clear_indicator_timer) { | ||||
| 		loop_remove_timer(state->eventloop, state->clear_indicator_timer); | ||||
| 	} | ||||
| 	state->clear_indicator_timer = loop_add_timer( | ||||
| 			state->eventloop, 3000, clear_indicator, state); | ||||
| } | ||||
| 
 | ||||
| static void clear_password(void *data) { | ||||
| 	struct swaylock_state *state = data; | ||||
| 	state->clear_password_timer = NULL; | ||||
| 	state->auth_state = AUTH_STATE_CLEAR; | ||||
| 	clear_password_buffer(&state->password); | ||||
| 	damage_state(state); | ||||
| 	schedule_indicator_clear(state); | ||||
| } | ||||
| 
 | ||||
| static void schedule_password_clear(struct swaylock_state *state) { | ||||
| 	if (state->clear_password_timer) { | ||||
| 		loop_remove_timer(state->eventloop, state->clear_password_timer); | ||||
| 	} | ||||
| 	state->clear_password_timer = loop_add_timer( | ||||
| 			state->eventloop, 10000, clear_password, state); | ||||
| } | ||||
| 
 | ||||
| static void handle_preverify_timeout(void *data) { | ||||
| 	struct swaylock_state *state = data; | ||||
| 	state->verify_password_timer = NULL; | ||||
| } | ||||
| 
 | ||||
| static void submit_password(struct swaylock_state *state) { | ||||
| 	if (state->args.ignore_empty && state->password.len == 0) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	state->auth_state = AUTH_STATE_VALIDATING; | ||||
| 	damage_state(state); | ||||
| 
 | ||||
| 	// We generally want to wait until all surfaces are showing the
 | ||||
| 	// "verifying" state before we go and verify the password, because
 | ||||
| 	// verifying it is a blocking operation. However, if the surface is on
 | ||||
| 	// an output with DPMS off then it won't update, so we set a timer.
 | ||||
| 	state->verify_password_timer = loop_add_timer( | ||||
| 			state->eventloop, 50, handle_preverify_timeout, state); | ||||
| 
 | ||||
| 	while (state->run_display && state->verify_password_timer) { | ||||
| 		errno = 0; | ||||
| 		if (wl_display_flush(state->display) == -1 && errno != EAGAIN) { | ||||
| 			break; | ||||
| 		} | ||||
| 		loop_poll(state->eventloop); | ||||
| 
 | ||||
| 		bool ok = 1; | ||||
| 		struct swaylock_surface *surface; | ||||
| 		wl_list_for_each(surface, &state->surfaces, link) { | ||||
| 			if (surface->dirty) { | ||||
| 				ok = 0; | ||||
| 			} | ||||
| 		} | ||||
| 		if (ok) { | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	wl_display_flush(state->display); | ||||
| 
 | ||||
| 	if (attempt_password(&state->password)) { | ||||
| 		state->run_display = false; | ||||
| 		return; | ||||
| 	} | ||||
| 	state->auth_state = AUTH_STATE_INVALID; | ||||
| 	damage_state(state); | ||||
| 	schedule_indicator_clear(state); | ||||
| } | ||||
| 
 | ||||
| void swaylock_handle_key(struct swaylock_state *state, | ||||
| 		xkb_keysym_t keysym, uint32_t codepoint) { | ||||
| 	switch (keysym) { | ||||
| 	case XKB_KEY_KP_Enter: /* fallthrough */ | ||||
| 	case XKB_KEY_Return: | ||||
| 		submit_password(state); | ||||
| 		break; | ||||
| 	case XKB_KEY_Delete: | ||||
| 	case XKB_KEY_BackSpace: | ||||
| 		if (backspace(&state->password)) { | ||||
| 			state->auth_state = AUTH_STATE_BACKSPACE; | ||||
| 		} else { | ||||
| 			state->auth_state = AUTH_STATE_CLEAR; | ||||
| 		} | ||||
| 		damage_state(state); | ||||
| 		schedule_indicator_clear(state); | ||||
| 		schedule_password_clear(state); | ||||
| 		break; | ||||
| 	case XKB_KEY_Escape: | ||||
| 		clear_password_buffer(&state->password); | ||||
| 		state->auth_state = AUTH_STATE_CLEAR; | ||||
| 		damage_state(state); | ||||
| 		schedule_indicator_clear(state); | ||||
| 		break; | ||||
| 	case XKB_KEY_Caps_Lock: | ||||
| 	case XKB_KEY_Shift_L: | ||||
| 	case XKB_KEY_Shift_R: | ||||
| 	case XKB_KEY_Control_L: | ||||
| 	case XKB_KEY_Control_R: | ||||
| 	case XKB_KEY_Meta_L: | ||||
| 	case XKB_KEY_Meta_R: | ||||
| 	case XKB_KEY_Alt_L: | ||||
| 	case XKB_KEY_Alt_R: | ||||
| 	case XKB_KEY_Super_L: | ||||
| 	case XKB_KEY_Super_R: | ||||
| 		state->auth_state = AUTH_STATE_INPUT_NOP; | ||||
| 		damage_state(state); | ||||
| 		schedule_indicator_clear(state); | ||||
| 		schedule_password_clear(state); | ||||
| 		break; | ||||
| 	case XKB_KEY_d: | ||||
| 		if (state->xkb.control) { | ||||
| 			submit_password(state); | ||||
| 			break; | ||||
| 		} | ||||
| 		// fallthrough
 | ||||
| 	case XKB_KEY_c: /* fallthrough */ | ||||
| 	case XKB_KEY_u: | ||||
| 		if (state->xkb.control) { | ||||
| 			clear_password_buffer(&state->password); | ||||
| 			state->auth_state = AUTH_STATE_CLEAR; | ||||
| 			damage_state(state); | ||||
| 			schedule_indicator_clear(state); | ||||
| 			break; | ||||
| 		} | ||||
| 		// fallthrough
 | ||||
| 	default: | ||||
| 		if (codepoint) { | ||||
| 			append_ch(&state->password, codepoint); | ||||
| 			state->auth_state = AUTH_STATE_INPUT; | ||||
| 			damage_state(state); | ||||
| 			schedule_indicator_clear(state); | ||||
| 			schedule_password_clear(state); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| @ -1,189 +0,0 @@ | ||||
| #include <math.h> | ||||
| #include <stdlib.h> | ||||
| #include <wayland-client.h> | ||||
| #include "cairo.h" | ||||
| #include "background-image.h" | ||||
| #include "swaylock/swaylock.h" | ||||
| 
 | ||||
| #define M_PI 3.14159265358979323846 | ||||
| const float TYPE_INDICATOR_RANGE = M_PI / 3.0f; | ||||
| const float TYPE_INDICATOR_BORDER_THICKNESS = M_PI / 128.0f; | ||||
| 
 | ||||
| static void set_color_for_state(cairo_t *cairo, struct swaylock_state *state, | ||||
| 		struct swaylock_colorset *colorset) { | ||||
| 	if (state->auth_state == AUTH_STATE_VALIDATING) { | ||||
| 		cairo_set_source_u32(cairo, colorset->verifying); | ||||
| 	} else if (state->auth_state == AUTH_STATE_INVALID) { | ||||
| 		cairo_set_source_u32(cairo, colorset->wrong); | ||||
| 	} else if (state->auth_state == AUTH_STATE_CLEAR) { | ||||
| 		cairo_set_source_u32(cairo, colorset->cleared); | ||||
| 	} else { | ||||
| 		if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) { | ||||
| 			cairo_set_source_u32(cairo, colorset->caps_lock); | ||||
| 		} else if (state->xkb.caps_lock && !state->args.show_caps_lock_indicator && | ||||
| 				state->args.show_caps_lock_text) { | ||||
| 			uint32_t inputtextcolor = state->args.colors.text.input; | ||||
| 			state->args.colors.text.input = state->args.colors.text.caps_lock; | ||||
| 			cairo_set_source_u32(cairo, colorset->input); | ||||
| 			state->args.colors.text.input = inputtextcolor; | ||||
| 		} else { | ||||
| 			cairo_set_source_u32(cairo, colorset->input); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void render_frame(struct swaylock_surface *surface) { | ||||
| 	struct swaylock_state *state = surface->state; | ||||
| 
 | ||||
| 	int buffer_width = surface->width * surface->scale; | ||||
| 	int buffer_height = surface->height * surface->scale; | ||||
| 	if (buffer_width == 0 || buffer_height == 0) { | ||||
| 		return; // not yet configured
 | ||||
| 	} | ||||
| 
 | ||||
| 	surface->current_buffer = get_next_buffer(state->shm, | ||||
| 			surface->buffers, buffer_width, buffer_height); | ||||
| 	if (surface->current_buffer == NULL) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	cairo_t *cairo = surface->current_buffer->cairo; | ||||
| 	cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST); | ||||
| 	cairo_font_options_t *fo = cairo_font_options_create(); | ||||
| 	cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL); | ||||
| 	cairo_font_options_set_antialias(fo, CAIRO_ANTIALIAS_SUBPIXEL); | ||||
| 	cairo_font_options_set_subpixel_order(fo, to_cairo_subpixel_order(surface->subpixel)); | ||||
| 	cairo_set_font_options(cairo, fo); | ||||
| 	cairo_font_options_destroy(fo); | ||||
| 	cairo_identity_matrix(cairo); | ||||
| 
 | ||||
| 	cairo_save(cairo); | ||||
| 	cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE); | ||||
| 	if (state->args.mode == BACKGROUND_MODE_SOLID_COLOR || !surface->image) { | ||||
| 		cairo_set_source_u32(cairo, state->args.colors.background); | ||||
| 		cairo_paint(cairo); | ||||
| 	} else { | ||||
| 		render_background_image(cairo, surface->image, | ||||
| 				state->args.mode, buffer_width, buffer_height); | ||||
| 	} | ||||
| 	cairo_restore(cairo); | ||||
| 	cairo_identity_matrix(cairo); | ||||
| 
 | ||||
| 	int arc_radius = state->args.radius * surface->scale; | ||||
| 	int arc_thickness = state->args.thickness * surface->scale; | ||||
| 	float type_indicator_border_thickness = | ||||
| 		TYPE_INDICATOR_BORDER_THICKNESS * surface->scale; | ||||
| 
 | ||||
| 	if (state->args.show_indicator && state->auth_state != AUTH_STATE_IDLE) { | ||||
| 		// Draw circle
 | ||||
| 		cairo_set_line_width(cairo, arc_thickness); | ||||
| 		cairo_arc(cairo, buffer_width / 2, buffer_height / 2, arc_radius, | ||||
| 				0, 2 * M_PI); | ||||
| 		set_color_for_state(cairo, state, &state->args.colors.inside); | ||||
| 		cairo_fill_preserve(cairo); | ||||
| 		set_color_for_state(cairo, state, &state->args.colors.ring); | ||||
| 		cairo_stroke(cairo); | ||||
| 
 | ||||
| 		// Draw a message
 | ||||
| 		char *text = NULL; | ||||
| 		set_color_for_state(cairo, state, &state->args.colors.text); | ||||
| 		cairo_select_font_face(cairo, state->args.font, | ||||
| 				CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); | ||||
| 		cairo_set_font_size(cairo, arc_radius / 3.0f); | ||||
| 		switch (state->auth_state) { | ||||
| 		case AUTH_STATE_VALIDATING: | ||||
| 			text = "verifying"; | ||||
| 			break; | ||||
| 		case AUTH_STATE_INVALID: | ||||
| 			text = "wrong"; | ||||
| 			break; | ||||
| 		case AUTH_STATE_CLEAR: | ||||
| 			text = "cleared"; | ||||
| 			break; | ||||
| 		case AUTH_STATE_INPUT: | ||||
| 		case AUTH_STATE_INPUT_NOP: | ||||
| 		case AUTH_STATE_BACKSPACE: | ||||
| 			if (state->xkb.caps_lock && state->args.show_caps_lock_text) { | ||||
| 				text = "Caps Lock"; | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			break; | ||||
| 		} | ||||
| 
 | ||||
| 		if (text) { | ||||
| 			cairo_text_extents_t extents; | ||||
| 			double x, y; | ||||
| 			cairo_text_extents(cairo, text, &extents); | ||||
| 			x = (buffer_width / 2) - | ||||
| 				(extents.width / 2 + extents.x_bearing); | ||||
| 			y = (buffer_height / 2) - | ||||
| 				(extents.height / 2 + extents.y_bearing); | ||||
| 
 | ||||
| 			cairo_move_to(cairo, x, y); | ||||
| 			cairo_show_text(cairo, text); | ||||
| 			cairo_close_path(cairo); | ||||
| 			cairo_new_sub_path(cairo); | ||||
| 		} | ||||
| 
 | ||||
| 		// Typing indicator: Highlight random part on keypress
 | ||||
| 		if (state->auth_state == AUTH_STATE_INPUT | ||||
| 				|| state->auth_state == AUTH_STATE_BACKSPACE) { | ||||
| 			static double highlight_start = 0; | ||||
| 			highlight_start += | ||||
| 				(rand() % (int)(M_PI * 100)) / 100.0 + M_PI * 0.5; | ||||
| 			cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | ||||
| 					arc_radius, highlight_start, | ||||
| 					highlight_start + TYPE_INDICATOR_RANGE); | ||||
| 			if (state->auth_state == AUTH_STATE_INPUT) { | ||||
| 				if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) { | ||||
| 					cairo_set_source_u32(cairo, state->args.colors.caps_lock_key_highlight); | ||||
| 				} else { | ||||
| 					cairo_set_source_u32(cairo, state->args.colors.key_highlight); | ||||
| 				} | ||||
| 			} else { | ||||
| 				if (state->xkb.caps_lock && state->args.show_caps_lock_indicator) { | ||||
| 					cairo_set_source_u32(cairo, state->args.colors.caps_lock_bs_highlight); | ||||
| 				} else { | ||||
| 					cairo_set_source_u32(cairo, state->args.colors.bs_highlight); | ||||
| 				} | ||||
| 			} | ||||
| 			cairo_stroke(cairo); | ||||
| 
 | ||||
| 			// Draw borders
 | ||||
| 			cairo_set_source_u32(cairo, state->args.colors.separator); | ||||
| 			cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | ||||
| 					arc_radius, highlight_start, | ||||
| 					highlight_start + type_indicator_border_thickness); | ||||
| 			cairo_stroke(cairo); | ||||
| 
 | ||||
| 			cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | ||||
| 					arc_radius, highlight_start + TYPE_INDICATOR_RANGE, | ||||
| 					highlight_start + TYPE_INDICATOR_RANGE + | ||||
| 						type_indicator_border_thickness); | ||||
| 			cairo_stroke(cairo); | ||||
| 		} | ||||
| 
 | ||||
| 		// Draw inner + outer border of the circle
 | ||||
| 		set_color_for_state(cairo, state, &state->args.colors.line); | ||||
| 		cairo_set_line_width(cairo, 2.0 * surface->scale); | ||||
| 		cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | ||||
| 				arc_radius - arc_thickness / 2, 0, 2 * M_PI); | ||||
| 		cairo_stroke(cairo); | ||||
| 		cairo_arc(cairo, buffer_width / 2, buffer_height / 2, | ||||
| 				arc_radius + arc_thickness / 2, 0, 2 * M_PI); | ||||
| 		cairo_stroke(cairo); | ||||
| 	} | ||||
| 
 | ||||
| 	wl_surface_set_buffer_scale(surface->surface, surface->scale); | ||||
| 	wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0); | ||||
| 	wl_surface_damage(surface->surface, 0, 0, surface->width, surface->height); | ||||
| 	wl_surface_commit(surface->surface); | ||||
| } | ||||
| 
 | ||||
| void render_frames(struct swaylock_state *state) { | ||||
| 	struct swaylock_surface *surface; | ||||
| 	wl_list_for_each(surface, &state->surfaces, link) { | ||||
| 		render_frame(surface); | ||||
| 	} | ||||
| } | ||||
| @ -1,178 +0,0 @@ | ||||
| #include <assert.h> | ||||
| #include <stdlib.h> | ||||
| #include <sys/mman.h> | ||||
| #include <unistd.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include <xkbcommon/xkbcommon.h> | ||||
| #include "swaylock/swaylock.h" | ||||
| #include "swaylock/seat.h" | ||||
| 
 | ||||
| static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, | ||||
| 		uint32_t format, int32_t fd, uint32_t size) { | ||||
| 	struct swaylock_state *state = data; | ||||
| 	if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { | ||||
| 		close(fd); | ||||
| 		wlr_log(WLR_ERROR, "Unknown keymap format %d, aborting", format); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); | ||||
| 	if (map_shm == MAP_FAILED) { | ||||
| 		close(fd); | ||||
| 		wlr_log(WLR_ERROR, "Unable to initialize keymap shm, aborting"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	struct xkb_keymap *keymap = xkb_keymap_new_from_string( | ||||
| 			state->xkb.context, map_shm, XKB_KEYMAP_FORMAT_TEXT_V1, 0); | ||||
| 	munmap(map_shm, size); | ||||
| 	close(fd); | ||||
| 	assert(keymap); | ||||
| 	struct xkb_state *xkb_state = xkb_state_new(keymap); | ||||
| 	assert(xkb_state); | ||||
| 	xkb_keymap_unref(state->xkb.keymap); | ||||
| 	xkb_state_unref(state->xkb.state); | ||||
| 	state->xkb.keymap = keymap; | ||||
| 	state->xkb.state = xkb_state; | ||||
| } | ||||
| 
 | ||||
| static void keyboard_enter(void *data, struct wl_keyboard *wl_keyboard, | ||||
| 		uint32_t serial, struct wl_surface *surface, struct wl_array *keys) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| static void keyboard_leave(void *data, struct wl_keyboard *wl_keyboard, | ||||
| 		uint32_t serial, struct wl_surface *surface) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| static void keyboard_key(void *data, struct wl_keyboard *wl_keyboard, | ||||
| 		uint32_t serial, uint32_t time, uint32_t key, uint32_t _key_state) { | ||||
| 	struct swaylock_state *state = data; | ||||
| 	enum wl_keyboard_key_state key_state = _key_state; | ||||
| 	xkb_keysym_t sym = xkb_state_key_get_one_sym(state->xkb.state, key + 8); | ||||
| 	uint32_t keycode = key_state == WL_KEYBOARD_KEY_STATE_PRESSED ? | ||||
| 		key + 8 : 0; | ||||
| 	uint32_t codepoint = xkb_state_key_get_utf32(state->xkb.state, keycode); | ||||
| 	if (key_state == WL_KEYBOARD_KEY_STATE_PRESSED) { | ||||
| 		swaylock_handle_key(state, sym, codepoint); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard, | ||||
| 		uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, | ||||
| 		uint32_t mods_locked, uint32_t group) { | ||||
| 	struct swaylock_state *state = data; | ||||
| 	xkb_state_update_mask(state->xkb.state, | ||||
| 		mods_depressed, mods_latched, mods_locked, 0, 0, group); | ||||
| 	int caps_lock = xkb_state_mod_name_is_active(state->xkb.state, | ||||
| 		XKB_MOD_NAME_CAPS, XKB_STATE_MODS_LOCKED); | ||||
| 	if (caps_lock != state->xkb.caps_lock) { | ||||
| 		state->xkb.caps_lock = caps_lock; | ||||
| 		damage_state(state); | ||||
| 	} | ||||
| 	state->xkb.control = xkb_state_mod_name_is_active(state->xkb.state, | ||||
| 		XKB_MOD_NAME_CTRL, | ||||
| 		XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| static void keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard, | ||||
| 		int32_t rate, int32_t delay) { | ||||
| 	// TODO
 | ||||
| } | ||||
| 
 | ||||
| static const struct wl_keyboard_listener keyboard_listener = { | ||||
| 	.keymap = keyboard_keymap, | ||||
| 	.enter = keyboard_enter, | ||||
| 	.leave = keyboard_leave, | ||||
| 	.key = keyboard_key, | ||||
| 	.modifiers = keyboard_modifiers, | ||||
| 	.repeat_info = keyboard_repeat_info, | ||||
| }; | ||||
| 
 | ||||
| static void wl_pointer_enter(void *data, struct wl_pointer *wl_pointer, | ||||
| 		uint32_t serial, struct wl_surface *surface, | ||||
| 		wl_fixed_t surface_x, wl_fixed_t surface_y) { | ||||
| 	wl_pointer_set_cursor(wl_pointer, serial, NULL, 0, 0); | ||||
| } | ||||
| 
 | ||||
| static void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer, | ||||
| 		uint32_t serial, struct wl_surface *surface) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| static void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, | ||||
| 		uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| static void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, | ||||
| 		uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, | ||||
| 		uint32_t time, uint32_t axis, wl_fixed_t value) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| static void wl_pointer_frame(void *data, struct wl_pointer *wl_pointer) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| static void wl_pointer_axis_source(void *data, struct wl_pointer *wl_pointer, | ||||
| 		uint32_t axis_source) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| static void wl_pointer_axis_stop(void *data, struct wl_pointer *wl_pointer, | ||||
| 		uint32_t time, uint32_t axis) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| static void wl_pointer_axis_discrete(void *data, struct wl_pointer *wl_pointer, | ||||
| 		uint32_t axis, int32_t discrete) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| static const struct wl_pointer_listener pointer_listener = { | ||||
| 	.enter = wl_pointer_enter, | ||||
| 	.leave = wl_pointer_leave, | ||||
| 	.motion = wl_pointer_motion, | ||||
| 	.button = wl_pointer_button, | ||||
| 	.axis = wl_pointer_axis, | ||||
| 	.frame = wl_pointer_frame, | ||||
| 	.axis_source = wl_pointer_axis_source, | ||||
| 	.axis_stop = wl_pointer_axis_stop, | ||||
| 	.axis_discrete = wl_pointer_axis_discrete, | ||||
| }; | ||||
| 
 | ||||
| static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, | ||||
| 		enum wl_seat_capability caps) { | ||||
| 	struct swaylock_seat *seat = data; | ||||
| 	if (seat->pointer) { | ||||
| 		wl_pointer_release(seat->pointer); | ||||
| 		seat->pointer = NULL; | ||||
| 	} | ||||
| 	if (seat->keyboard) { | ||||
| 		wl_keyboard_release(seat->keyboard); | ||||
| 		seat->keyboard = NULL; | ||||
| 	} | ||||
| 	if ((caps & WL_SEAT_CAPABILITY_POINTER)) { | ||||
| 		seat->pointer = wl_seat_get_pointer(wl_seat); | ||||
| 		wl_pointer_add_listener(seat->pointer, &pointer_listener, NULL); | ||||
| 	} | ||||
| 	if ((caps & WL_SEAT_CAPABILITY_KEYBOARD)) { | ||||
| 		seat->keyboard = wl_seat_get_keyboard(wl_seat); | ||||
| 		wl_keyboard_add_listener(seat->keyboard, &keyboard_listener, seat->state); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void seat_handle_name(void *data, struct wl_seat *wl_seat, | ||||
| 		const char *name) { | ||||
| 	// Who cares
 | ||||
| } | ||||
| 
 | ||||
| const struct wl_seat_listener seat_listener = { | ||||
| 	.capabilities = seat_handle_capabilities, | ||||
| 	.name = seat_handle_name, | ||||
| }; | ||||
| @ -1,155 +0,0 @@ | ||||
| #define _XOPEN_SOURCE // for crypt
 | ||||
| #include <pwd.h> | ||||
| #include <shadow.h> | ||||
| #include <stdbool.h> | ||||
| #include <sys/types.h> | ||||
| #include <unistd.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include "swaylock/swaylock.h" | ||||
| #ifdef __GLIBC__ | ||||
| // GNU, you damn slimy bastard
 | ||||
| #include <crypt.h> | ||||
| #endif | ||||
| 
 | ||||
| static int comm[2][2]; | ||||
| 
 | ||||
| static void clear_buffer(void *buf, size_t bytes) { | ||||
| 	volatile char *buffer = buf; | ||||
| 	volatile char zero = '\0'; | ||||
| 	for (size_t i = 0; i < bytes; ++i) { | ||||
| 		buffer[i] = zero; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void run_child(void) { | ||||
| 	/* This code runs as root */ | ||||
| 	struct passwd *pwent = getpwuid(getuid()); | ||||
| 	if (!pwent) { | ||||
| 		wlr_log_errno(WLR_ERROR, "failed to getpwuid"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 	char *encpw = pwent->pw_passwd; | ||||
| 	if (strcmp(encpw, "x") == 0) { | ||||
| 		struct spwd *swent = getspnam(pwent->pw_name); | ||||
| 		if (!swent) { | ||||
| 			wlr_log_errno(WLR_ERROR, "failed to getspnam"); | ||||
| 			exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 		encpw = swent->sp_pwdp; | ||||
| 	} | ||||
| 
 | ||||
| 	/* We don't need any additional logging here because the parent process will
 | ||||
| 	 * also fail here and will handle logging for us. */ | ||||
| 	if (setgid(getgid()) != 0) { | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 	if (setuid(getuid()) != 0) { | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 
 | ||||
| 	/* This code does not run as root */ | ||||
| 	wlr_log(WLR_DEBUG, "prepared to authorize user %s", pwent->pw_name); | ||||
| 
 | ||||
| 	size_t size; | ||||
| 	char *buf; | ||||
| 	while (1) { | ||||
| 		ssize_t amt; | ||||
| 		amt = read(comm[0][0], &size, sizeof(size)); | ||||
| 		if (amt == 0) { | ||||
| 			break; | ||||
| 		} else if (amt < 0) { | ||||
| 			wlr_log_errno(WLR_ERROR, "read pw request"); | ||||
| 		} | ||||
| 		wlr_log(WLR_DEBUG, "received pw check request"); | ||||
| 		buf = malloc(size); | ||||
| 		if (!buf) { | ||||
| 			wlr_log_errno(WLR_ERROR, "failed to malloc pw buffer"); | ||||
| 			exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 		size_t offs = 0; | ||||
| 		do { | ||||
| 			amt = read(comm[0][0], &buf[offs], size - offs); | ||||
| 			if (amt <= 0) { | ||||
| 				wlr_log_errno(WLR_ERROR, "failed to read pw"); | ||||
| 				exit(EXIT_FAILURE); | ||||
| 			} | ||||
| 			offs += (size_t)amt; | ||||
| 		} while (offs < size); | ||||
| 		bool result = false; | ||||
| 		char *c = crypt(buf, encpw); | ||||
| 		if (c == NULL) { | ||||
| 			wlr_log_errno(WLR_ERROR, "crypt"); | ||||
| 		} | ||||
| 		result = strcmp(c, encpw) == 0; | ||||
| 		if (write(comm[1][1], &result, sizeof(result)) != sizeof(result)) { | ||||
| 			wlr_log_errno(WLR_ERROR, "failed to write pw check result"); | ||||
| 			clear_buffer(buf, size); | ||||
| 			exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 		clear_buffer(buf, size); | ||||
| 		free(buf); | ||||
| 	} | ||||
| 
 | ||||
| 	clear_buffer(encpw, strlen(encpw)); | ||||
| 	exit(EXIT_SUCCESS); | ||||
| } | ||||
| 
 | ||||
| void initialize_pw_backend(void) { | ||||
| 	if (geteuid() != 0) { | ||||
| 		wlr_log(WLR_ERROR, "swaylock needs to be setuid to read /etc/shadow"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 	if (pipe(comm[0]) != 0) { | ||||
| 		wlr_log_errno(WLR_ERROR, "failed to create pipe"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 	if (pipe(comm[1]) != 0) { | ||||
| 		wlr_log_errno(WLR_ERROR, "failed to create pipe"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 	pid_t child = fork(); | ||||
| 	if (child == 0) { | ||||
| 		close(comm[0][1]); | ||||
| 		close(comm[1][0]); | ||||
| 		run_child(); | ||||
| 	} else if (child < 0) { | ||||
| 		wlr_log_errno(WLR_ERROR, "failed to fork"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 	close(comm[0][0]); | ||||
| 	close(comm[1][1]); | ||||
| 	if (setgid(getgid()) != 0) { | ||||
| 		wlr_log_errno(WLR_ERROR, "Unable to drop root"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| 	if (setuid(getuid()) != 0) { | ||||
| 		wlr_log_errno(WLR_ERROR, "Unable to drop root"); | ||||
| 		exit(EXIT_FAILURE); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool attempt_password(struct swaylock_password *pw) { | ||||
| 	bool result = false; | ||||
| 	size_t len = pw->len + 1; | ||||
| 	size_t offs = 0; | ||||
| 	if (write(comm[0][1], &len, sizeof(len)) < 0) { | ||||
| 		wlr_log_errno(WLR_ERROR, "Failed to request pw check"); | ||||
| 		goto ret; | ||||
| 	} | ||||
| 	do { | ||||
| 		ssize_t amt = write(comm[0][1], &pw->buffer[offs], len - offs); | ||||
| 		if (amt < 0) { | ||||
| 			wlr_log_errno(WLR_ERROR, "Failed to write pw buffer"); | ||||
| 			goto ret; | ||||
| 		} | ||||
| 		offs += amt; | ||||
| 	} while (offs < len); | ||||
| 	if (read(comm[1][0], &result, sizeof(result)) != sizeof(result)) { | ||||
| 		wlr_log_errno(WLR_ERROR, "Failed to read pw result"); | ||||
| 		goto ret; | ||||
| 	} | ||||
| 	wlr_log(WLR_DEBUG, "pw result: %d", result); | ||||
| ret: | ||||
| 	clear_password_buffer(pw); | ||||
| 	return result; | ||||
| } | ||||
| @ -1,167 +0,0 @@ | ||||
| swaylock(1) | ||||
| 
 | ||||
| # NAME | ||||
| 
 | ||||
| swaylock - Screen locker for Wayland | ||||
| 
 | ||||
| # SYNOPSIS | ||||
| 
 | ||||
| _swaylock_ [options...] | ||||
| 
 | ||||
| Locks your Wayland session. | ||||
| 
 | ||||
| # OPTIONS | ||||
| 
 | ||||
| *-C, --config* <path> | ||||
| 	The config file to use. By default, the following paths are checked: | ||||
| 	_$HOME/.swaylock/config_, _$XDG\_CONFIG\_HOME/swaylock/config_, and | ||||
| 	_SYSCONFDIR/swaylock/config_. All flags aside from this one are valid | ||||
| 	options in the configuration file using the format _long-option=value_. | ||||
| 	For options such as _ignore-empty-password_, just supply the _long-option_. | ||||
| 	All leading dashes should be omitted and the equals sign is required for | ||||
| 	flags that take an argument. | ||||
| 
 | ||||
| *-e, --ignore-empty-password* | ||||
| 	When an empty password is provided by the user, do not validate it. | ||||
| 
 | ||||
| *-f, --daemonize* | ||||
| 	Detach from the controlling terminal after locking. | ||||
| 
 | ||||
| 	Note: this is the default behavior of i3lock. | ||||
| 
 | ||||
| *-h, --help* | ||||
| 	Show help message and quit. | ||||
| 
 | ||||
| *-v, --version* | ||||
| 	Show the version number and quit. | ||||
| 
 | ||||
| # APPEARANCE | ||||
| 
 | ||||
| *-u, --no-unlock-indicator* | ||||
| 	Disable the unlock indicator. | ||||
| 
 | ||||
| *-i, --image* [<output>:]<path> | ||||
| 	Display the given image, optionally only on the given output. Use -c to set | ||||
| 	a background color. | ||||
| 
 | ||||
| *-L, --disable-caps-lock-text* | ||||
| 	Disable the Caps Lock Text. | ||||
| 
 | ||||
| *-l, --indicator-caps-lock* | ||||
| 	Show the current Caps Lock state also on the indicator. | ||||
| 
 | ||||
| *-s, --scaling* | ||||
| 	Scaling mode for images: _stretch_, _fill_, _fit_, _center_, or _tile_. | ||||
| 
 | ||||
| *-t, --tiling* | ||||
| 	Same as --scaling=tile. | ||||
| 
 | ||||
| *-c, --color* <rrggbb[aa]> | ||||
| 	Turn the screen into the given color. If -i is used, this sets the | ||||
| 	background of the image to the given color. Defaults to white (FFFFFF), or | ||||
| 	transparent (00000000) if an image is in use. | ||||
| 
 | ||||
| *--bs-hl-color* <rrggbb[aa]> | ||||
| 	Sets the color of backspace highlight segments. | ||||
| 
 | ||||
| *--caps-lock-bs-hl-color* <rrggbb[aa]> | ||||
| 	Sets the color of backspace highlight segments when Caps Lock is active. | ||||
| 
 | ||||
| *--caps-lock-bs-hl-color* <rrggbb[aa]> | ||||
| 	Sets the color of the key press highlight segments when Caps Lock is active. | ||||
| 
 | ||||
| *--font* <font> | ||||
| 	Sets the font of the text inside the indicator. | ||||
| 
 | ||||
| *--indicator-radius* <radius> | ||||
| 	Sets the radius of the indicator to _radius_ pixels. The default value is | ||||
| 	50. | ||||
| 
 | ||||
| *--indicator-thickness* <thickness> | ||||
| 	Sets the thickness of the indicator to _thickness_ pixels. The default value | ||||
| 	is 10. | ||||
| 
 | ||||
| *--inside-color* <rrggbb[aa]> | ||||
| 	Sets the color of the inside of the indicator when typing or idle. | ||||
| 
 | ||||
| *--inside-clear-color* <rrggbb[aa]> | ||||
| 	Sets the color of the inside of the indicator when cleared. | ||||
| 
 | ||||
| *--inside-caps-lock-color* <rrggbb[aa]> | ||||
| 	Sets the color of the inside of the indicator when Caps Lock is active. | ||||
| 
 | ||||
| *--inside-ver-color* <rrggbb[aa]> | ||||
| 	Sets the color of the inside of the indicator when verifying. | ||||
| 
 | ||||
| *--inside-wrong-color* <rrggbb[aa]> | ||||
| 	Sets the color of the inside of the indicator when invalid. | ||||
| 
 | ||||
| *--key-hl-color* <rrggbb[aa]> | ||||
| 	Sets the color of key press highlight segments. | ||||
| 
 | ||||
| *--line-color* <rrggbb[aa]> | ||||
| 	Sets the color of the lines that separate the inside and outside of the | ||||
| 	indicator when typing or idle. | ||||
| 
 | ||||
| *--line-clear-color* <rrggbb[aa]> | ||||
| 	Sets the color of the lines that separate the inside and outside of the | ||||
| 	indicator when cleared. | ||||
| 
 | ||||
| *--line-caps-lock-color* <rrggbb[aa]> | ||||
| 	Sets the color of the line between the inside and ring when Caps Lock | ||||
| 	is active. | ||||
| 
 | ||||
| *--line-ver-color* <rrggbb[aa]> | ||||
| 	Sets the color of the lines that separate the inside and outside of the | ||||
| 	indicator when verifying. | ||||
| 
 | ||||
| *--line-wrong-color* <rrggbb[aa]> | ||||
| 	Sets the color of the lines that separate the inside and outside of the | ||||
| 	indicator when invalid. | ||||
| 
 | ||||
| *-n, --line-uses-inside* | ||||
| 	Use the color of the inside of the indicator for the line separating the | ||||
| 	inside and outside of the indicator. | ||||
| 
 | ||||
| *-r, --line-uses-ring* | ||||
| 	Use the outer ring's color for the line separating the inside and outside of | ||||
| 	the indicator. | ||||
| 
 | ||||
| *--ring-color* <rrggbb[aa]> | ||||
| 	Sets the color of the outside of the indicator when typing or idle. | ||||
| 
 | ||||
| *--ring-clear-color* <rrggbb[aa]> | ||||
| 	Sets the color of the outside of the indicator when cleared. | ||||
| 
 | ||||
| *--ring-caps-lock-color* <rrggbb[aa]> | ||||
| 	Sets the color of the ring of the indicator when Caps Lock is active. | ||||
| 
 | ||||
| *--ring-ver-color* <rrggbb[aa]> | ||||
| 	Sets the color of the outside of the indicator when verifying. | ||||
| 
 | ||||
| *--ring-wrong-color* <rrggbb[aa]> | ||||
| 	Sets the color of the outside of the indicator when invalid. | ||||
| 
 | ||||
| *--separator-color* <rrggbb[aa]> | ||||
| 	Sets the color of the lines that separate highlight segments. | ||||
| 
 | ||||
| *--text-color* <rrggbb[aa]> | ||||
| 	Sets the color of the text inside the indicator when typing or idle. | ||||
| 
 | ||||
| *--text-clear-color* <rrggbb[aa]> | ||||
| 	Sets the color of the text inside the indicator when cleared. | ||||
| 
 | ||||
| *--text-caps-lock-color* <rrggbb[aa]> | ||||
| 	Sets the color of the text when Caps Lock is active. | ||||
| 
 | ||||
| *--text-ver-color* <rrggbb[aa]> | ||||
| 	Sets the color of the text inside the indicator when verifying. | ||||
| 
 | ||||
| *--text-wrong-color* <rrggbb[aa]> | ||||
| 	Sets the color of the text inside the indicator when invalid. | ||||
| 
 | ||||
| # AUTHORS | ||||
| 
 | ||||
| Maintained by Drew DeVault <sir@cmpwn.com>, who is assisted by other open | ||||
| source contributors. For more information about sway development, see | ||||
| https://github.com/swaywm/sway. | ||||
					Loading…
					
					
				
		Reference in new issue