File: comm.c

package info (click to toggle)
swaylock 1.8.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 328 kB
  • sloc: ansic: 3,177; makefile: 6
file content (145 lines) | stat: -rw-r--r-- 2,981 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <assert.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include "comm.h"
#include "log.h"
#include "swaylock.h"
#include "password-buffer.h"

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

static ssize_t read_full(int fd, void *dst, size_t size) {
	char *buf = dst;
	size_t offset = 0;
	while (offset < size) {
		ssize_t n = read(fd, &buf[offset], size - offset);
		if (n < 0) {
			if (errno == EINTR) {
				continue;
			}
			swaylock_log_errno(LOG_ERROR, "read() failed");
			return -1;
		} else if (n == 0) {
			if (offset == 0) {
				return 0;
			}
			swaylock_log(LOG_ERROR, "read() failed: unexpected EOF");
			return -1;
		}
		offset += n;
	}
	return offset;
}

static bool write_full(int fd, const void *src, size_t size) {
	const char *buf = src;
	size_t offset = 0;
	while (offset < size) {
		ssize_t n = write(fd, &buf[offset], size - offset);
		if (n <= 0) {
			assert(n != 0);
			if (errno == EINTR) {
				continue;
			}
			swaylock_log_errno(LOG_ERROR, "write() failed");
			return false;
		}
		offset += n;
	}
	return true;
}

ssize_t read_comm_request(char **buf_ptr) {
	int fd = comm[0][0];

	size_t size;
	ssize_t n = read_full(fd, &size, sizeof(size));
	if (n <= 0) {
		return n;
	}
	assert(size > 0);

	swaylock_log(LOG_DEBUG, "received pw check request");

	char *buf = password_buffer_create(size);
	if (!buf) {
		return -1;
	}

	if (read_full(fd, buf, size) <= 0) {
		swaylock_log_errno(LOG_ERROR, "failed to read pw");
		return -1;
	}

	assert(buf[size - 1] == '\0');
	*buf_ptr = buf;
	return size;
}

bool write_comm_reply(bool success) {
	return write_full(comm[1][1], &success, sizeof(success));
}

bool spawn_comm_child(void) {
	if (pipe(comm[0]) != 0) {
		swaylock_log_errno(LOG_ERROR, "failed to create pipe");
		return false;
	}
	if (pipe(comm[1]) != 0) {
		swaylock_log_errno(LOG_ERROR, "failed to create pipe");
		return false;
	}
	pid_t child = fork();
	if (child < 0) {
		swaylock_log_errno(LOG_ERROR, "failed to fork");
		return false;
	} else if (child == 0) {
		struct sigaction sa = {
			.sa_handler = SIG_IGN,
		};
		sigaction(SIGUSR1, &sa, NULL);
		close(comm[0][1]);
		close(comm[1][0]);
		run_pw_backend_child();
	}
	close(comm[0][0]);
	close(comm[1][1]);
	return true;
}

bool write_comm_request(struct swaylock_password *pw) {
	bool result = false;
	int fd = comm[0][1];

	size_t size = pw->len + 1;
	if (!write_full(fd, &size, sizeof(size))) {
		swaylock_log_errno(LOG_ERROR, "Failed to write pw size");
		goto out;
	}

	if (!write_full(fd, pw->buffer, size)) {
		swaylock_log_errno(LOG_ERROR, "Failed to write pw buffer");
		goto out;
	}

	result = true;

out:
	clear_password_buffer(pw);
	return result;
}

bool read_comm_reply(bool *auth_success) {
	if (read_full(comm[1][0], auth_success, sizeof(*auth_success)) <= 0) {
		swaylock_log(LOG_ERROR, "Failed to read pw result");
		return false;
	}
	return true;
}

int get_comm_reply_fd(void) {
	return comm[1][0];
}