Skip to content
4 changes: 4 additions & 0 deletions cairo.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#endif

uint32_t color_with_alpha(uint32_t color, uint8_t alpha) {
return (color & 0xFFFFFF00) | alpha;
}

void cairo_set_source_u32(cairo_t *cairo, uint32_t color) {
cairo_set_source_rgba(cairo,
(color >> (3*8) & 0xFF) / 255.0,
Expand Down
153 changes: 112 additions & 41 deletions comm.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,41 +9,87 @@

static int comm[2][2] = {{-1, -1}, {-1, -1}};

ssize_t read_comm_request(char **buf_ptr) {
ssize_t write_string(int fd, const char *string, size_t len) {
size_t offs = 0;
if (write(fd, &len, sizeof(len)) < 0) {
swaylock_log_errno(LOG_ERROR, "Failed to write string size");
return -1;
}

do {
ssize_t amt = write(fd, &string[offs], len - offs);
if (amt < 0) {
swaylock_log_errno(LOG_ERROR, "Failed to write string");
//TODO: different return value for different error?
return -1;
}
offs += amt;
} while (offs < len);

return (ssize_t) len;
}

ssize_t read_string(int fd, char *(*alloc)(size_t), char **output) {
size_t size;
ssize_t amt;
amt = read(comm[0][0], &size, sizeof(size));
if (amt == 0) {
ssize_t amt = read(fd, &size, sizeof(size));
if (amt <= 0) {
swaylock_log_errno(LOG_ERROR, "Failed to read string size");
return amt;
}
if (size == 0) {
return 0;
} else if (amt < 0) {
swaylock_log_errno(LOG_ERROR, "read pw request");
return -1;
}
swaylock_log(LOG_DEBUG, "received pw check request");
char *buf = password_buffer_create(size);
char *buf = alloc(size);
if (!buf) {
return -1;
}
size_t offs = 0;
do {
amt = read(comm[0][0], &buf[offs], size - offs);
ssize_t amt = read(fd, &buf[offs], size - offs);
if (amt <= 0) {
swaylock_log_errno(LOG_ERROR, "failed to read pw");
swaylock_log_errno(LOG_ERROR, "Failed to read string");
return -1;
}
offs += (size_t)amt;
} while (offs < size);

*buf_ptr = buf;
*output = buf;
return size;
}

bool write_comm_reply(bool success) {
ssize_t read_comm_prompt_response(char **buf_ptr) {
ssize_t amt = read_string(comm[0][0], password_buffer_create, buf_ptr);
swaylock_log(LOG_DEBUG, "received response to prompt");
if (amt == 0) {
return 0;
} else if (amt < 0) {
swaylock_log(LOG_ERROR, "Error reading prompt response");
return -1;
}
return amt;
}

ssize_t write_comm_text_message_from_backend(const char *msg) {
enum backend_message_type msg_type = BACKEND_MESSAGE_TYPE_TEXT;
if (write(comm[1][1], &msg_type, sizeof(msg_type)) != sizeof(msg_type)) {
swaylock_log_errno(LOG_ERROR, "failed to write message type");
return -1;
}
return write_string(comm[1][1], msg, strlen(msg) + 1);
}

ssize_t write_comm_auth_result_from_backend(bool success) {
enum backend_message_type msg_type = BACKEND_MESSAGE_TYPE_AUTH_RESULT;
if (write(comm[1][1], &msg_type, sizeof(msg_type)) != sizeof(msg_type)) {
swaylock_log_errno(LOG_ERROR, "failed to write message type");
return -1;
}

if (write(comm[1][1], &success, sizeof(success)) != sizeof(success)) {
swaylock_log_errno(LOG_ERROR, "failed to write pw check result");
return false;
swaylock_log_errno(LOG_ERROR, "failed to write authentication result");
return -1;
}
return true;
return sizeof(success);
}

bool spawn_comm_child(void) {
Expand All @@ -69,41 +115,66 @@ bool spawn_comm_child(void) {
return true;
}

bool write_comm_request(struct swaylock_password *pw) {
bool write_comm_prompt_response(struct swaylock_password *pw) {
bool result = false;
ssize_t amt = write_string(comm[0][1], pw->buffer, pw->len + 1);

size_t len = pw->len + 1;
size_t offs = 0;
if (write(comm[0][1], &len, sizeof(len)) < 0) {
swaylock_log_errno(LOG_ERROR, "Failed to request pw check");
goto out;
if (amt < 0) {
swaylock_log_errno(LOG_ERROR, "Failed to write prompt response");
} else {
result = true;
}

do {
ssize_t amt = write(comm[0][1], &pw->buffer[offs], len - offs);
if (amt < 0) {
swaylock_log_errno(LOG_ERROR, "Failed to write pw buffer");
goto out;
}
offs += amt;
} while (offs < len);

result = true;

out:
clear_password_buffer(pw);
return result;
}

bool read_comm_reply(void) {
bool result = false;
if (read(comm[1][0], &result, sizeof(result)) != sizeof(result)) {
swaylock_log_errno(LOG_ERROR, "Failed to read pw result");
result = false;
char *malloc_str(size_t size) {
char *res = (char *) malloc(size * sizeof(char));
if (!res) {
swaylock_log_errno(LOG_ERROR, "failed to allocate string");
return NULL;
}
return result;
return res;
}

ssize_t read_comm_message_from_backend(enum backend_message_type *msg_type, void **data) {
enum backend_message_type read_type;
void *read_data;

if (read(comm[1][0], &read_type, sizeof(read_type)) != sizeof(read_type)) {
swaylock_log_errno(LOG_ERROR, "Failed to read message type from backend");
return -1;
}

ssize_t amt;
switch(read_type) {
case BACKEND_MESSAGE_TYPE_TEXT:
amt = read_string(comm[1][0], malloc_str, (char **) &read_data);
if (amt < 0) {
swaylock_log(LOG_ERROR, "Error reading string from backend");
return -1;
} else if (amt == 0) {
read_data = NULL; //TODO: good?
}
break;

case BACKEND_MESSAGE_TYPE_AUTH_RESULT:
read_data = malloc(sizeof(bool));
amt = read(comm[1][0], (bool *) read_data, sizeof(bool));
if (amt != sizeof(bool)) {
swaylock_log(LOG_ERROR, "Error reading boolean from backend");
return -1;
}
break;

}

*msg_type = read_type;
*data = read_data;
return amt;
}

int get_comm_reply_fd(void) {
int get_comm_backend_message_fd(void) {
return comm[1][0];
}
1 change: 1 addition & 0 deletions include/cairo.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#endif

uint32_t color_with_alpha(uint32_t color, uint8_t alpha);
void cairo_set_source_u32(cairo_t *cairo, uint32_t color);
cairo_subpixel_order_t to_cairo_subpixel_order(enum wl_output_subpixel subpixel);

Expand Down
53 changes: 45 additions & 8 deletions include/comm.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,51 @@

struct swaylock_password;

enum backend_message_type {
//TODO: error messages separately?
BACKEND_MESSAGE_TYPE_TEXT, // Text info, error message or prompt
BACKEND_MESSAGE_TYPE_AUTH_RESULT, // Boolean indicating authorization success or failure
};

bool spawn_comm_child(void);
ssize_t read_comm_request(char **buf_ptr);
bool write_comm_reply(bool success);
// Requests the provided password to be checked. The password is always cleared
// when the function returns.
bool write_comm_request(struct swaylock_password *pw);
bool read_comm_reply(void);
// FD to poll for password authentication replies.
int get_comm_reply_fd(void);

// Write a string to a file descriptor by first sending the size and then the
// string data. len should be the length of the string, *including* null
// termination. Returns the number of bytes in the written string, *not* the
// total no. of bytes written - the total number is the return value plus
// sizeof(size_t).
ssize_t write_string(int fd, const char *string, size_t len);

// Read a string from a file descriptor by first reading the size, allocating
// memory to output using alloc(size) and then reading the string data to it.
// Returns the number of bytes in the string, *not* the total no. of bytes read
// - the total number is the return value plus sizeof(size_t).
ssize_t read_string(int fd, char *(*alloc)(size_t), char **output);

// Read a message from the password checking backend (e.g. a prompt or the
// result of authentication) in the main thread. Read first the message type,
// then the associated data itself (size + string data for strings, just the
// boolean value for booleans).
// Returns the no. of bytes in the *data* that was read, the total no. of bytes
// read is the return value plus sizeof(enum backend_message_type).
ssize_t read_comm_message_from_backend(enum backend_message_type *msg_type, void **data);
// Write a string containing a message from the backend
// Returns the no. of bytes in the *message* that was written, the total no. of
// bytes written is the return value plus sizeof(enum backend_message_type).
ssize_t write_comm_text_message_from_backend(const char *msg);
// Write a boolean value indicating the result of authentication
// Returns the no. of bytes in the *data* that was written (i.e. sizeof(bool)),
// the total no. of bytes written is the return value plus
// sizeof(enum backend_message_type).
ssize_t write_comm_auth_result_from_backend(bool success);

// Read / write the response typed by the user (password, PIN code, etc) to a
// prompt sent by the backend. The password buffer is always cleared when the
// function returns. //TODO: verify
ssize_t read_comm_prompt_response(char **buf_ptr);
bool write_comm_prompt_response(struct swaylock_password *pw);

// FD to poll for messages from the backend
int get_comm_backend_message_fd(void);

#endif
2 changes: 1 addition & 1 deletion include/log.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void _swaylock_log(enum log_importance verbosity, const char *format, ...)
const char *_swaylock_strip_path(const char *filepath);

#define swaylock_log(verb, fmt, ...) \
_swaylock_log(verb, "[%s:%d] " fmt, _swaylock_strip_path(__FILE__), \
_swaylock_log(verb, "[%d:%s:%d] " fmt, getpid(), _swaylock_strip_path(__FILE__), \
__LINE__, ##__VA_ARGS__)

#define swaylock_log_errno(verb, fmt, ...) \
Expand Down
11 changes: 11 additions & 0 deletions include/swaylock.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ struct swaylock_password {
char *buffer;
};

struct swaylock_backend_message_list {
size_t num_messages;
size_t max_num_messages;
char **messages;
};

struct swaylock_state {
struct loop *eventloop;
struct loop_timer *input_idle_timer; // timer to reset input state to IDLE
Expand All @@ -90,6 +96,7 @@ struct swaylock_state {
struct wl_list images;
struct swaylock_args args;
struct swaylock_password password;
struct swaylock_backend_message_list backend_message_list; // backend messages displayed in the UI
struct swaylock_xkb xkb;
cairo_surface_t *test_surface;
cairo_t *test_cairo; // used to estimate font/text sizes
Expand Down Expand Up @@ -144,4 +151,8 @@ void initialize_pw_backend(int argc, char **argv);
void run_pw_backend_child(void);
void clear_buffer(char *buf, size_t size);

// Add a message to the list of displayed backend messages. Creates a copy of
// the string, it can be freed after calling this function.
void add_backend_message(struct swaylock_state *state, char *msg);

#endif
Loading