Implement logging and remove wlroots dependency

This implements a simpler version of the wlroots logger for swaylock.
With this logger, the dependency on wlroots can be dropped. This also
adds a debug flag and disables debugging output by default
This commit is contained in:
Brian Ashworth 2019-01-14 23:30:54 -05:00
parent fcf1bd4ebe
commit e3935ad143
13 changed files with 195 additions and 85 deletions

View File

@ -33,7 +33,6 @@ channel or shoot an email to sir@cmpwn.com for advice.
Install dependencies: Install dependencies:
* meson \* * meson \*
* [wlroots](https://github.com/swaywm/wlroots)
* wayland * wayland
* wayland-protocols \* * wayland-protocols \*
* pango * pango

View File

@ -1,8 +1,8 @@
#include <assert.h> #include <assert.h>
#include <stdbool.h> #include <stdbool.h>
#include <wlr/util/log.h>
#include "background-image.h" #include "background-image.h"
#include "cairo.h" #include "cairo.h"
#include "log.h"
enum background_mode parse_background_mode(const char *mode) { enum background_mode parse_background_mode(const char *mode) {
if (strcmp(mode, "stretch") == 0) { if (strcmp(mode, "stretch") == 0) {
@ -18,7 +18,7 @@ enum background_mode parse_background_mode(const char *mode) {
} else if (strcmp(mode, "solid_color") == 0) { } else if (strcmp(mode, "solid_color") == 0) {
return BACKGROUND_MODE_SOLID_COLOR; return BACKGROUND_MODE_SOLID_COLOR;
} }
wlr_log(WLR_ERROR, "Unsupported background mode: %s", mode); swaylock_log(LOG_ERROR, "Unsupported background mode: %s", mode);
return BACKGROUND_MODE_INVALID; return BACKGROUND_MODE_INVALID;
} }
@ -28,7 +28,7 @@ cairo_surface_t *load_background_image(const char *path) {
GError *err = NULL; GError *err = NULL;
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err); GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file(path, &err);
if (!pixbuf) { if (!pixbuf) {
wlr_log(WLR_ERROR, "Failed to load background image (%s).", swaylock_log(LOG_ERROR, "Failed to load background image (%s).",
err->message); err->message);
return false; return false;
} }
@ -38,11 +38,11 @@ cairo_surface_t *load_background_image(const char *path) {
image = cairo_image_surface_create_from_png(path); image = cairo_image_surface_create_from_png(path);
#endif // HAVE_GDK_PIXBUF #endif // HAVE_GDK_PIXBUF
if (!image) { if (!image) {
wlr_log(WLR_ERROR, "Failed to read background image."); swaylock_log(LOG_ERROR, "Failed to read background image.");
return NULL; return NULL;
} }
if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) { if (cairo_surface_status(image) != CAIRO_STATUS_SUCCESS) {
wlr_log(WLR_ERROR, "Failed to read background image: %s." swaylock_log(LOG_ERROR, "Failed to read background image: %s."
#if !HAVE_GDK_PIXBUF #if !HAVE_GDK_PIXBUF
"\nSway was compiled without gdk_pixbuf support, so only" "\nSway was compiled without gdk_pixbuf support, so only"
"\nPNG images can be loaded. This is the likely cause." "\nPNG images can be loaded. This is the likely cause."

36
include/log.h Normal file
View File

@ -0,0 +1,36 @@
#ifndef _SWAYLOCK_LOG_H
#define _SWAYLOCK_LOG_H
#include <stdarg.h>
#include <string.h>
#include <errno.h>
enum log_importance {
LOG_SILENT = 0,
LOG_ERROR = 1,
LOG_INFO = 2,
LOG_DEBUG = 3,
LOG_IMPORTANCE_LAST,
};
void swaylock_log_init(enum log_importance verbosity);
#ifdef __GNUC__
#define _ATTRIB_PRINTF(start, end) __attribute__((format(printf, start, end)))
#else
#define _ATTRIB_PRINTF(start, end)
#endif
void _swaylock_log(enum log_importance verbosity, const char *format, ...)
_ATTRIB_PRINTF(2, 3);
const char *_swaylock_strip_path(const char *filepath);
#define swaylock_log(verb, fmt, ...) \
_swaylock_log(verb, "[%s:%d] " fmt, _swaylock_strip_path(__FILE__), \
__LINE__, ##__VA_ARGS__)
#define swaylock_log_errno(verb, fmt, ...) \
swaylock_log(verb, fmt ": %s", ##__VA_ARGS__, strerror(errno))
#endif

68
log.c Normal file
View File

@ -0,0 +1,68 @@
#define _POSIX_C_SOURCE 199506L
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "log.h"
static enum log_importance log_importance = LOG_ERROR;
static const char *verbosity_colors[] = {
[LOG_SILENT] = "",
[LOG_ERROR ] = "\x1B[1;31m",
[LOG_INFO ] = "\x1B[1;34m",
[LOG_DEBUG ] = "\x1B[1;30m",
};
void swaylock_log_init(enum log_importance verbosity) {
if (verbosity < LOG_IMPORTANCE_LAST) {
log_importance = verbosity;
}
}
void _swaylock_log(enum log_importance verbosity, const char *fmt, ...) {
if (verbosity > log_importance) {
return;
}
va_list args;
va_start(args, fmt);
// prefix the time to the log message
struct tm result;
time_t t = time(NULL);
struct tm *tm_info = localtime_r(&t, &result);
char buffer[26];
// generate time prefix
strftime(buffer, sizeof(buffer), "%F %T - ", tm_info);
fprintf(stderr, "%s", buffer);
unsigned c = (verbosity < LOG_IMPORTANCE_LAST)
? verbosity : LOG_IMPORTANCE_LAST - 1;
if (isatty(STDERR_FILENO)) {
fprintf(stderr, "%s", verbosity_colors[c]);
}
vfprintf(stderr, fmt, args);
if (isatty(STDERR_FILENO)) {
fprintf(stderr, "\x1B[0m");
}
fprintf(stderr, "\n");
va_end(args);
}
const char *_swaylock_strip_path(const char *filepath) {
if (*filepath == '.') {
while (*filepath == '.' || *filepath == '/') {
++filepath;
}
}
return filepath;
}

8
loop.c
View File

@ -7,8 +7,8 @@
#include <poll.h> #include <poll.h>
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include <wlr/util/log.h>
#include "list.h" #include "list.h"
#include "log.h"
#include "loop.h" #include "loop.h"
struct loop_fd_event { struct loop_fd_event {
@ -34,7 +34,7 @@ struct loop {
struct loop *loop_create(void) { struct loop *loop_create(void) {
struct loop *loop = calloc(1, sizeof(struct loop)); struct loop *loop = calloc(1, sizeof(struct loop));
if (!loop) { if (!loop) {
wlr_log(WLR_ERROR, "Unable to allocate memory for loop"); swaylock_log(LOG_ERROR, "Unable to allocate memory for loop");
return NULL; return NULL;
} }
loop->fd_capacity = 10; loop->fd_capacity = 10;
@ -107,7 +107,7 @@ void loop_add_fd(struct loop *loop, int fd, short mask,
void (*callback)(int fd, short mask, void *data), void *data) { void (*callback)(int fd, short mask, void *data), void *data) {
struct loop_fd_event *event = calloc(1, sizeof(struct loop_fd_event)); struct loop_fd_event *event = calloc(1, sizeof(struct loop_fd_event));
if (!event) { if (!event) {
wlr_log(WLR_ERROR, "Unable to allocate memory for event"); swaylock_log(LOG_ERROR, "Unable to allocate memory for event");
return; return;
} }
event->callback = callback; event->callback = callback;
@ -129,7 +129,7 @@ struct loop_timer *loop_add_timer(struct loop *loop, int ms,
void (*callback)(void *data), void *data) { void (*callback)(void *data), void *data) {
struct loop_timer *timer = calloc(1, sizeof(struct loop_timer)); struct loop_timer *timer = calloc(1, sizeof(struct loop_timer));
if (!timer) { if (!timer) {
wlr_log(WLR_ERROR, "Unable to allocate memory for timer"); swaylock_log(LOG_ERROR, "Unable to allocate memory for timer");
return NULL; return NULL;
} }
timer->callback = callback; timer->callback = callback;

84
main.c
View File

@ -15,29 +15,17 @@
#include <unistd.h> #include <unistd.h>
#include <wayland-client.h> #include <wayland-client.h>
#include <wordexp.h> #include <wordexp.h>
#include <wlr/util/log.h>
#include "background-image.h" #include "background-image.h"
#include "cairo.h"
#include "log.h"
#include "loop.h"
#include "pool-buffer.h"
#include "seat.h" #include "seat.h"
#include "swaylock.h" #include "swaylock.h"
#include "pool-buffer.h"
#include "cairo.h"
#include "loop.h"
#include "wlr-input-inhibitor-unstable-v1-client-protocol.h" #include "wlr-input-inhibitor-unstable-v1-client-protocol.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h" #include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h" #include "xdg-output-unstable-v1-client-protocol.h"
void sway_terminate(int exit_code) {
exit(exit_code);
}
void sway_abort(const char *format, ...) {
va_list args;
va_start(args, format);
_wlr_vlog(WLR_ERROR, format, args);
va_end(args);
sway_terminate(EXIT_FAILURE);
}
static uint32_t parse_color(const char *color) { static uint32_t parse_color(const char *color) {
if (color[0] == '#') { if (color[0] == '#') {
++color; ++color;
@ -45,7 +33,8 @@ static uint32_t parse_color(const char *color) {
int len = strlen(color); int len = strlen(color);
if (len != 6 && len != 8) { if (len != 6 && len != 8) {
wlr_log(WLR_DEBUG, "Invalid color %s, defaulting to color 0xFFFFFFFF", color); swaylock_log(LOG_DEBUG, "Invalid color %s, defaulting to 0xFFFFFFFF",
color);
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }
uint32_t res = (uint32_t)strtoul(color, NULL, 16); uint32_t res = (uint32_t)strtoul(color, NULL, 16);
@ -70,7 +59,7 @@ int lenient_strcmp(char *a, char *b) {
static void daemonize(void) { static void daemonize(void) {
int fds[2]; int fds[2];
if (pipe(fds) != 0) { if (pipe(fds) != 0) {
wlr_log(WLR_ERROR, "Failed to pipe"); swaylock_log(LOG_ERROR, "Failed to pipe");
exit(1); exit(1);
} }
if (fork() == 0) { if (fork() == 0) {
@ -94,7 +83,7 @@ static void daemonize(void) {
close(fds[1]); close(fds[1]);
uint8_t success; uint8_t success;
if (read(fds[0], &success, 1) != 1 || !success) { if (read(fds[0], &success, 1) != 1 || !success) {
wlr_log(WLR_ERROR, "Failed to daemonize"); swaylock_log(LOG_ERROR, "Failed to daemonize");
exit(1); exit(1);
} }
close(fds[0]); close(fds[0]);
@ -278,7 +267,7 @@ static void handle_xdg_output_logical_position(void *data,
static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output, static void handle_xdg_output_name(void *data, struct zxdg_output_v1 *output,
const char *name) { const char *name) {
wlr_log(WLR_DEBUG, "output name is %s", name); swaylock_log(LOG_DEBUG, "output name is %s", name);
struct swaylock_surface *surface = data; struct swaylock_surface *surface = data;
surface->xdg_output = output; surface->xdg_output = output;
surface->output_name = strdup(name); surface->output_name = strdup(name);
@ -391,11 +380,11 @@ static void load_image(char *arg, struct swaylock_state *state) {
wl_list_for_each_safe(iter_image, temp, &state->images, link) { wl_list_for_each_safe(iter_image, temp, &state->images, link) {
if (lenient_strcmp(iter_image->output_name, image->output_name) == 0) { if (lenient_strcmp(iter_image->output_name, image->output_name) == 0) {
if (image->output_name) { if (image->output_name) {
wlr_log(WLR_DEBUG, swaylock_log(LOG_DEBUG,
"Replacing image defined for output %s with %s", "Replacing image defined for output %s with %s",
image->output_name, image->path); image->output_name, image->path);
} else { } else {
wlr_log(WLR_DEBUG, "Replacing default image with %s", swaylock_log(LOG_DEBUG, "Replacing default image with %s",
image->path); image->path);
} }
wl_list_remove(&iter_image->link); wl_list_remove(&iter_image->link);
@ -422,8 +411,8 @@ static void load_image(char *arg, struct swaylock_state *state) {
return; return;
} }
wl_list_insert(&state->images, &image->link); wl_list_insert(&state->images, &image->link);
wlr_log(WLR_DEBUG, "Loaded image %s for output %s", swaylock_log(LOG_DEBUG, "Loaded image %s for output %s", image->path,
image->path, image->output_name ? image->output_name : "*"); image->output_name ? image->output_name : "*");
} }
static void set_default_colors(struct swaylock_colors *colors) { static void set_default_colors(struct swaylock_colors *colors) {
@ -505,6 +494,7 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
static struct option long_options[] = { static struct option long_options[] = {
{"config", required_argument, NULL, 'C'}, {"config", required_argument, NULL, 'C'},
{"color", required_argument, NULL, 'c'}, {"color", required_argument, NULL, 'c'},
{"debug", no_argument, NULL, 'd'},
{"ignore-empty-password", no_argument, NULL, 'e'}, {"ignore-empty-password", no_argument, NULL, 'e'},
{"daemonize", no_argument, NULL, 'f'}, {"daemonize", no_argument, NULL, 'f'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
@ -556,6 +546,8 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
"Path to the config file.\n" "Path to the config file.\n"
" -c, --color <color> " " -c, --color <color> "
"Turn the screen into the given color instead of white.\n" "Turn the screen into the given color instead of white.\n"
" -d, --debug "
"Enable debugging output.\n"
" -e, --ignore-empty-password " " -e, --ignore-empty-password "
"When an empty password is provided, do not validate it.\n" "When an empty password is provided, do not validate it.\n"
" -f, --daemonize " " -f, --daemonize "
@ -651,7 +643,8 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
optind = 1; optind = 1;
while (1) { while (1) {
int opt_idx = 0; int opt_idx = 0;
c = getopt_long(argc, argv, "c:efhi:Llnrs:tuvC:", long_options, &opt_idx); c = getopt_long(argc, argv, "c:defhi:Llnrs:tuvC:", long_options,
&opt_idx);
if (c == -1) { if (c == -1) {
break; break;
} }
@ -667,6 +660,9 @@ static int parse_options(int argc, char **argv, struct swaylock_state *state,
state->args.mode = BACKGROUND_MODE_SOLID_COLOR; state->args.mode = BACKGROUND_MODE_SOLID_COLOR;
} }
break; break;
case 'd':
swaylock_log_init(LOG_DEBUG);
break;
case 'e': case 'e':
if (state) { if (state) {
state->args.ignore_empty = true; state->args.ignore_empty = true;
@ -889,12 +885,12 @@ static char *get_config_path(void) {
char *home = getenv("HOME"); char *home = getenv("HOME");
char *config_home = malloc(strlen(home) + strlen("/.config") + 1); char *config_home = malloc(strlen(home) + strlen("/.config") + 1);
if (!config_home) { if (!config_home) {
wlr_log(WLR_ERROR, "Unable to allocate $HOME/.config"); swaylock_log(LOG_ERROR, "Unable to allocate $HOME/.config");
} else { } else {
strcpy(config_home, home); strcpy(config_home, home);
strcat(config_home, "/.config"); strcat(config_home, "/.config");
setenv("XDG_CONFIG_HOME", config_home, 1); setenv("XDG_CONFIG_HOME", config_home, 1);
wlr_log(WLR_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home); swaylock_log(LOG_DEBUG, "Set XDG_CONFIG_HOME to %s", config_home);
free(config_home); free(config_home);
} }
} }
@ -919,7 +915,7 @@ static int load_config(char *path, struct swaylock_state *state,
enum line_mode *line_mode) { enum line_mode *line_mode) {
FILE *config = fopen(path, "r"); FILE *config = fopen(path, "r");
if (!config) { if (!config) {
wlr_log(WLR_ERROR, "Failed to read config. Running without it."); swaylock_log(LOG_ERROR, "Failed to read config. Running without it.");
return 0; return 0;
} }
char *line = NULL; char *line = NULL;
@ -938,7 +934,7 @@ static int load_config(char *path, struct swaylock_state *state,
continue; continue;
} }
wlr_log(WLR_DEBUG, "Config Line #%d: %s", line_number, line); swaylock_log(LOG_DEBUG, "Config Line #%d: %s", line_number, line);
char flag[nread + 3]; char flag[nread + 3];
sprintf(flag, "--%s", line); sprintf(flag, "--%s", line);
char *argv[] = {"swaylock", flag}; char *argv[] = {"swaylock", flag};
@ -961,7 +957,7 @@ static void display_in(int fd, short mask, void *data) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
wlr_log_init(WLR_DEBUG, NULL); swaylock_log_init(LOG_ERROR);
initialize_pw_backend(); initialize_pw_backend();
enum line_mode line_mode = LM_LINE; enum line_mode line_mode = LM_LINE;
@ -989,18 +985,20 @@ int main(int argc, char **argv) {
} }
if (config_path) { if (config_path) {
wlr_log(WLR_DEBUG, "Found config at %s", config_path); swaylock_log(LOG_DEBUG, "Found config at %s", config_path);
int config_status = load_config(config_path, &state, &line_mode); int config_status = load_config(config_path, &state, &line_mode);
free(config_path); free(config_path);
if (config_status != 0) { if (config_status != 0) {
free(state.args.font);
return config_status; return config_status;
} }
} }
if (argc > 1) { if (argc > 1) {
wlr_log(WLR_DEBUG, "Parsing CLI Args"); swaylock_log(LOG_DEBUG, "Parsing CLI Args");
int result = parse_options(argc, argv, &state, &line_mode, NULL); int result = parse_options(argc, argv, &state, &line_mode, NULL);
if (result != 0) { if (result != 0) {
free(state.args.font);
return result; return result;
} }
} }
@ -1014,7 +1012,8 @@ int main(int argc, char **argv) {
#ifdef __linux__ #ifdef __linux__
// Most non-linux platforms require root to mlock() // Most non-linux platforms require root to mlock()
if (mlock(state.password.buffer, sizeof(state.password.buffer)) != 0) { if (mlock(state.password.buffer, sizeof(state.password.buffer)) != 0) {
sway_abort("Unable to mlock() password memory."); swaylock_log(LOG_ERROR, "Unable to mlock() password memory.");
return EXIT_FAILURE;
} }
#endif #endif
@ -1022,9 +1021,11 @@ int main(int argc, char **argv) {
state.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); state.xkb.context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
state.display = wl_display_connect(NULL); state.display = wl_display_connect(NULL);
if (!state.display) { if (!state.display) {
sway_abort("Unable to connect to the compositor. " free(state.args.font);
swaylock_log(LOG_ERROR, "Unable to connect to the compositor. "
"If your compositor is running, check or set the " "If your compositor is running, check or set the "
"WAYLAND_DISPLAY environment variable."); "WAYLAND_DISPLAY environment variable.");
return EXIT_FAILURE;
} }
struct wl_registry *registry = wl_display_get_registry(state.display); struct wl_registry *registry = wl_display_get_registry(state.display);
@ -1032,19 +1033,22 @@ int main(int argc, char **argv) {
wl_display_roundtrip(state.display); wl_display_roundtrip(state.display);
assert(state.compositor && state.layer_shell && state.shm); assert(state.compositor && state.layer_shell && state.shm);
if (!state.input_inhibit_manager) { if (!state.input_inhibit_manager) {
wlr_log(WLR_ERROR, "Compositor does not support the input inhibitor " free(state.args.font);
"protocol, refusing to run insecurely"); swaylock_log(LOG_ERROR, "Compositor does not support the input "
"inhibitor protocol, refusing to run insecurely");
return 1; return 1;
} }
if (wl_list_empty(&state.surfaces)) { if (wl_list_empty(&state.surfaces)) {
wlr_log(WLR_DEBUG, "Exiting - no outputs to show on."); free(state.args.font);
swaylock_log(LOG_ERROR, "Exiting - no outputs to show on.");
return 0; return 0;
} }
zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager); zwlr_input_inhibit_manager_v1_get_inhibitor(state.input_inhibit_manager);
if (wl_display_roundtrip(state.display) == -1) { if (wl_display_roundtrip(state.display) == -1) {
wlr_log(WLR_ERROR, "Exiting - failed to inhibit input:" free(state.args.font);
swaylock_log(LOG_ERROR, "Exiting - failed to inhibit input:"
" is another lockscreen already running?"); " is another lockscreen already running?");
return 2; return 2;
} }
@ -1059,8 +1063,8 @@ int main(int argc, char **argv) {
} }
wl_display_roundtrip(state.display); wl_display_roundtrip(state.display);
} else { } else {
wlr_log(WLR_INFO, "Compositor does not support zxdg output manager, " swaylock_log(LOG_INFO, "Compositor does not support zxdg output "
"images assigned to named outputs will not work"); "manager, images assigned to named outputs will not work");
} }
struct swaylock_surface *surface; struct swaylock_surface *surface;

View File

@ -32,7 +32,6 @@ if is_freebsd
add_project_arguments('-D_C11_SOURCE', language: 'c') add_project_arguments('-D_C11_SOURCE', language: 'c')
endif endif
wlroots = dependency('wlroots', fallback: ['wlroots', 'wlroots'])
wayland_client = dependency('wayland-client') wayland_client = dependency('wayland-client')
wayland_protos = dependency('wayland-protocols', version: '>=1.14') wayland_protos = dependency('wayland-protocols', version: '>=1.14')
xkbcommon = dependency('xkbcommon') xkbcommon = dependency('xkbcommon')
@ -123,13 +122,13 @@ dependencies = [
pangocairo, pangocairo,
xkbcommon, xkbcommon,
wayland_client, wayland_client,
wlroots,
] ]
sources = [ sources = [
'background-image.c', 'background-image.c',
'cairo.c', 'cairo.c',
'list.c', 'list.c',
'log.c',
'loop.c', 'loop.c',
'main.c', 'main.c',
'pango.c', 'pango.c',

8
pam.c
View File

@ -5,7 +5,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <wlr/util/log.h> #include "log.h"
#include "swaylock.h" #include "swaylock.h"
void initialize_pw_backend(void) { void initialize_pw_backend(void) {
@ -43,15 +43,15 @@ bool attempt_password(struct swaylock_password *pw) {
int pam_err; int pam_err;
if ((pam_err = pam_start("swaylock", username, if ((pam_err = pam_start("swaylock", username,
&local_conversation, &local_auth_handle)) != PAM_SUCCESS) { &local_conversation, &local_auth_handle)) != PAM_SUCCESS) {
wlr_log(WLR_ERROR, "PAM returned error %d", pam_err); swaylock_log(LOG_ERROR, "PAM returned error %d", pam_err);
} }
if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) { if ((pam_err = pam_authenticate(local_auth_handle, 0)) != PAM_SUCCESS) {
wlr_log(WLR_ERROR, "pam_authenticate failed"); swaylock_log(LOG_ERROR, "pam_authenticate failed");
goto fail; goto fail;
} }
// TODO: only call pam_end once we succeed at authing. refresh tokens beforehand // 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) { if ((pam_err = pam_end(local_auth_handle, pam_err)) != PAM_SUCCESS) {
wlr_log(WLR_ERROR, "pam_end failed"); swaylock_log(LOG_ERROR, "pam_end failed");
goto fail; goto fail;
} }
clear_password_buffer(pw); clear_password_buffer(pw);

View File

@ -6,8 +6,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <wlr/util/log.h>
#include "cairo.h" #include "cairo.h"
#include "log.h"
static const char overflow[] = "[buffer overflow]"; static const char overflow[] = "[buffer overflow]";
static const int max_chars = 16384; static const int max_chars = 16384;
@ -70,8 +70,8 @@ PangoLayout *get_pango_layout(cairo_t *cairo, const char *font,
pango_layout_set_text(layout, buf, -1); pango_layout_set_text(layout, buf, -1);
free(buf); free(buf);
} else { } else {
wlr_log(WLR_ERROR, "pango_parse_markup '%s' -> error %s", text, swaylock_log(LOG_ERROR, "pango_parse_markup '%s' -> error %s",
error->message); text, error->message);
g_error_free(error); g_error_free(error);
markup = false; // fallback to plain text markup = false; // fallback to plain text
} }

View File

@ -4,11 +4,11 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <wlr/util/log.h>
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include "swaylock.h" #include "log.h"
#include "seat.h"
#include "loop.h" #include "loop.h"
#include "seat.h"
#include "swaylock.h"
#include "unicode.h" #include "unicode.h"
void clear_password_buffer(struct swaylock_password *pw) { void clear_password_buffer(struct swaylock_password *pw) {

6
seat.c
View File

@ -2,8 +2,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <unistd.h> #include <unistd.h>
#include <wlr/util/log.h>
#include <xkbcommon/xkbcommon.h> #include <xkbcommon/xkbcommon.h>
#include "log.h"
#include "swaylock.h" #include "swaylock.h"
#include "seat.h" #include "seat.h"
@ -12,13 +12,13 @@ static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
struct swaylock_state *state = data; struct swaylock_state *state = data;
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
close(fd); close(fd);
wlr_log(WLR_ERROR, "Unknown keymap format %d, aborting", format); swaylock_log(LOG_ERROR, "Unknown keymap format %d, aborting", format);
exit(1); exit(1);
} }
char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); char *map_shm = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
if (map_shm == MAP_FAILED) { if (map_shm == MAP_FAILED) {
close(fd); close(fd);
wlr_log(WLR_ERROR, "Unable to initialize keymap shm, aborting"); swaylock_log(LOG_ERROR, "Unable to initialize keymap shm, aborting");
exit(1); exit(1);
} }
struct xkb_keymap *keymap = xkb_keymap_new_from_string( struct xkb_keymap *keymap = xkb_keymap_new_from_string(

View File

@ -4,7 +4,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <wlr/util/log.h> #include "log.h"
#include "swaylock/swaylock.h" #include "swaylock/swaylock.h"
#ifdef __GLIBC__ #ifdef __GLIBC__
// GNU, you damn slimy bastard // GNU, you damn slimy bastard
@ -25,14 +25,14 @@ void run_child(void) {
/* This code runs as root */ /* This code runs as root */
struct passwd *pwent = getpwuid(getuid()); struct passwd *pwent = getpwuid(getuid());
if (!pwent) { if (!pwent) {
wlr_log_errno(WLR_ERROR, "failed to getpwuid"); swaylock_log_errno(LOG_ERROR, "failed to getpwuid");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
char *encpw = pwent->pw_passwd; char *encpw = pwent->pw_passwd;
if (strcmp(encpw, "x") == 0) { if (strcmp(encpw, "x") == 0) {
struct spwd *swent = getspnam(pwent->pw_name); struct spwd *swent = getspnam(pwent->pw_name);
if (!swent) { if (!swent) {
wlr_log_errno(WLR_ERROR, "failed to getspnam"); swaylock_log_errno(LOG_ERROR, "failed to getspnam");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
encpw = swent->sp_pwdp; encpw = swent->sp_pwdp;
@ -48,7 +48,7 @@ void run_child(void) {
} }
/* This code does not run as root */ /* This code does not run as root */
wlr_log(WLR_DEBUG, "prepared to authorize user %s", pwent->pw_name); swaylock_log(LOG_DEBUG, "prepared to authorize user %s", pwent->pw_name);
size_t size; size_t size;
char *buf; char *buf;
@ -58,19 +58,19 @@ void run_child(void) {
if (amt == 0) { if (amt == 0) {
break; break;
} else if (amt < 0) { } else if (amt < 0) {
wlr_log_errno(WLR_ERROR, "read pw request"); swaylock_log_errno(LOG_ERROR, "read pw request");
} }
wlr_log(WLR_DEBUG, "received pw check request"); swaylock_log(LOG_DEBUG, "received pw check request");
buf = malloc(size); buf = malloc(size);
if (!buf) { if (!buf) {
wlr_log_errno(WLR_ERROR, "failed to malloc pw buffer"); swaylock_log_errno(LOG_ERROR, "failed to malloc pw buffer");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
size_t offs = 0; size_t offs = 0;
do { do {
amt = read(comm[0][0], &buf[offs], size - offs); amt = read(comm[0][0], &buf[offs], size - offs);
if (amt <= 0) { if (amt <= 0) {
wlr_log_errno(WLR_ERROR, "failed to read pw"); swaylock_log_errno(LOG_ERROR, "failed to read pw");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
offs += (size_t)amt; offs += (size_t)amt;
@ -78,11 +78,11 @@ void run_child(void) {
bool result = false; bool result = false;
char *c = crypt(buf, encpw); char *c = crypt(buf, encpw);
if (c == NULL) { if (c == NULL) {
wlr_log_errno(WLR_ERROR, "crypt"); swaylock_log_errno(LOG_ERROR, "crypt");
} }
result = strcmp(c, encpw) == 0; result = strcmp(c, encpw) == 0;
if (write(comm[1][1], &result, sizeof(result)) != sizeof(result)) { if (write(comm[1][1], &result, sizeof(result)) != sizeof(result)) {
wlr_log_errno(WLR_ERROR, "failed to write pw check result"); swaylock_log_errno(LOG_ERROR, "failed to write pw check result");
clear_buffer(buf, size); clear_buffer(buf, size);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -96,15 +96,16 @@ void run_child(void) {
void initialize_pw_backend(void) { void initialize_pw_backend(void) {
if (geteuid() != 0) { if (geteuid() != 0) {
wlr_log(WLR_ERROR, "swaylock needs to be setuid to read /etc/shadow"); swaylock_log(LOG_ERROR,
"swaylock needs to be setuid to read /etc/shadow");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (pipe(comm[0]) != 0) { if (pipe(comm[0]) != 0) {
wlr_log_errno(WLR_ERROR, "failed to create pipe"); swaylock_log_errno(LOG_ERROR, "failed to create pipe");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (pipe(comm[1]) != 0) { if (pipe(comm[1]) != 0) {
wlr_log_errno(WLR_ERROR, "failed to create pipe"); swaylock_log_errno(LOG_ERROR, "failed to create pipe");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
pid_t child = fork(); pid_t child = fork();
@ -113,17 +114,17 @@ void initialize_pw_backend(void) {
close(comm[1][0]); close(comm[1][0]);
run_child(); run_child();
} else if (child < 0) { } else if (child < 0) {
wlr_log_errno(WLR_ERROR, "failed to fork"); swaylock_log_errno(LOG_ERROR, "failed to fork");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
close(comm[0][0]); close(comm[0][0]);
close(comm[1][1]); close(comm[1][1]);
if (setgid(getgid()) != 0) { if (setgid(getgid()) != 0) {
wlr_log_errno(WLR_ERROR, "Unable to drop root"); swaylock_log_errno(LOG_ERROR, "Unable to drop root");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (setuid(getuid()) != 0) { if (setuid(getuid()) != 0) {
wlr_log_errno(WLR_ERROR, "Unable to drop root"); swaylock_log_errno(LOG_ERROR, "Unable to drop root");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
@ -133,22 +134,22 @@ bool attempt_password(struct swaylock_password *pw) {
size_t len = pw->len + 1; size_t len = pw->len + 1;
size_t offs = 0; size_t offs = 0;
if (write(comm[0][1], &len, sizeof(len)) < 0) { if (write(comm[0][1], &len, sizeof(len)) < 0) {
wlr_log_errno(WLR_ERROR, "Failed to request pw check"); swaylock_log_errno(LOG_ERROR, "Failed to request pw check");
goto ret; goto ret;
} }
do { do {
ssize_t amt = write(comm[0][1], &pw->buffer[offs], len - offs); ssize_t amt = write(comm[0][1], &pw->buffer[offs], len - offs);
if (amt < 0) { if (amt < 0) {
wlr_log_errno(WLR_ERROR, "Failed to write pw buffer"); swaylock_log_errno(LOG_ERROR, "Failed to write pw buffer");
goto ret; goto ret;
} }
offs += amt; offs += amt;
} while (offs < len); } while (offs < len);
if (read(comm[1][0], &result, sizeof(result)) != sizeof(result)) { if (read(comm[1][0], &result, sizeof(result)) != sizeof(result)) {
wlr_log_errno(WLR_ERROR, "Failed to read pw result"); swaylock_log_errno(LOG_ERROR, "Failed to read pw result");
goto ret; goto ret;
} }
wlr_log(WLR_DEBUG, "pw result: %d", result); swaylock_log(LOG_DEBUG, "pw result: %d", result);
ret: ret:
clear_password_buffer(pw); clear_password_buffer(pw);
return result; return result;

View File

@ -21,6 +21,9 @@ Locks your Wayland session.
All leading dashes should be omitted and the equals sign is required for All leading dashes should be omitted and the equals sign is required for
flags that take an argument. flags that take an argument.
*-d, --debug*
Enable debugging output.
*-e, --ignore-empty-password* *-e, --ignore-empty-password*
When an empty password is provided by the user, do not validate it. When an empty password is provided by the user, do not validate it.