1#include <stdbool.h>
2#include <stdlib.h>
3#include <sys/types.h>
4#include <unistd.h>
5#include "comm.h"
6#include "log.h"
7#include "swaylock.h"
8#include "password-buffer.h"
9
10static int comm[2][2] = {{-1, -1}, {-1, -1}};
11
12ssize_t read_comm_request(char **buf_ptr) {
13 size_t size;
14 ssize_t amt;
15 amt = read(comm[0][0], &size, sizeof(size));
16 if (amt == 0) {
17 return 0;
18 } else if (amt < 0) {
19 swaylock_log_errno(LOG_ERROR, "read pw request");
20 return -1;
21 }
22 swaylock_log(LOG_DEBUG, "received pw check request");
23 char *buf = password_buffer_create(size);
24 if (!buf) {
25 return -1;
26 }
27 size_t offs = 0;
28 do {
29 amt = read(comm[0][0], &buf[offs], size - offs);
30 if (amt <= 0) {
31 swaylock_log_errno(LOG_ERROR, "failed to read pw");
32 return -1;
33 }
34 offs += (size_t)amt;
35 } while (offs < size);
36
37 *buf_ptr = buf;
38 return size;
39}
40
41bool write_comm_reply(bool success) {
42 if (write(comm[1][1], &success, sizeof(success)) != sizeof(success)) {
43 swaylock_log_errno(LOG_ERROR, "failed to write pw check result");
44 return false;
45 }
46 return true;
47}
48
49bool spawn_comm_child(void) {
50 if (pipe(comm[0]) != 0) {
51 swaylock_log_errno(LOG_ERROR, "failed to create pipe");
52 return false;
53 }
54 if (pipe(comm[1]) != 0) {
55 swaylock_log_errno(LOG_ERROR, "failed to create pipe");
56 return false;
57 }
58 pid_t child = fork();
59 if (child < 0) {
60 swaylock_log_errno(LOG_ERROR, "failed to fork");
61 return false;
62 } else if (child == 0) {
63 close(comm[0][1]);
64 close(comm[1][0]);
65 run_pw_backend_child();
66 }
67 close(comm[0][0]);
68 close(comm[1][1]);
69 return true;
70}
71
72bool write_comm_request(struct swaylock_password *pw) {
73 bool result = false;
74
75 size_t len = pw->len + 1;
76 size_t offs = 0;
77 if (write(comm[0][1], &len, sizeof(len)) < 0) {
78 swaylock_log_errno(LOG_ERROR, "Failed to request pw check");
79 goto out;
80 }
81
82 do {
83 ssize_t amt = write(comm[0][1], &pw->buffer[offs], len - offs);
84 if (amt < 0) {
85 swaylock_log_errno(LOG_ERROR, "Failed to write pw buffer");
86 goto out;
87 }
88 offs += amt;
89 } while (offs < len);
90
91 result = true;
92
93out:
94 clear_password_buffer(pw);
95 return result;
96}
97
98bool read_comm_reply(void) {
99 bool result = false;
100 if (read(comm[1][0], &result, sizeof(result)) != sizeof(result)) {
101 swaylock_log_errno(LOG_ERROR, "Failed to read pw result");
102 result = false;
103 }
104 return result;
105}
106
107int get_comm_reply_fd(void) {
108 return comm[1][0];
109}