]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/test-bus-server.c
util: split out escaping code into escape.[ch]
[thirdparty/systemd.git] / src / libsystemd / sd-bus / test-bus-server.c
CommitLineData
11c4c249
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
11c4c249
LP
22#include <stdlib.h>
23#include <pthread.h>
11c4c249
LP
24
25#include "log.h"
26#include "util.h"
27#include "macro.h"
28
29#include "sd-bus.h"
30#include "bus-internal.h"
057171ef 31#include "bus-util.h"
11c4c249
LP
32
33struct context {
34 int fds[2];
35
36 bool client_negotiate_unix_fds;
37 bool server_negotiate_unix_fds;
38
39 bool client_anonymous_auth;
40 bool server_anonymous_auth;
41};
42
43static void *server(void *p) {
44 struct context *c = p;
45 sd_bus *bus = NULL;
46 sd_id128_t id;
47 bool quit = false;
48 int r;
49
50 assert_se(sd_id128_randomize(&id) >= 0);
51
52 assert_se(sd_bus_new(&bus) >= 0);
e82c9509 53 assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
11c4c249 54 assert_se(sd_bus_set_server(bus, 1, id) >= 0);
11c4c249 55 assert_se(sd_bus_set_anonymous(bus, c->server_anonymous_auth) >= 0);
264ad849 56 assert_se(sd_bus_negotiate_fds(bus, c->server_negotiate_unix_fds) >= 0);
11c4c249
LP
57 assert_se(sd_bus_start(bus) >= 0);
58
59 while (!quit) {
60 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
61
62 r = sd_bus_process(bus, &m);
63 if (r < 0) {
da927ba9 64 log_error_errno(r, "Failed to process requests: %m");
11c4c249
LP
65 goto fail;
66 }
67
68 if (r == 0) {
69 r = sd_bus_wait(bus, (uint64_t) -1);
70 if (r < 0) {
da927ba9 71 log_error_errno(r, "Failed to wait: %m");
11c4c249
LP
72 goto fail;
73 }
74
75 continue;
76 }
77
78 if (!m)
79 continue;
80
81 log_info("Got message! member=%s", strna(sd_bus_message_get_member(m)));
82
83 if (sd_bus_message_is_method_call(m, "org.freedesktop.systemd.test", "Exit")) {
84
85 assert_se((sd_bus_can_send(bus, 'h') >= 1) == (c->server_negotiate_unix_fds && c->client_negotiate_unix_fds));
86
df2d202e 87 r = sd_bus_message_new_method_return(m, &reply);
11c4c249 88 if (r < 0) {
da927ba9 89 log_error_errno(r, "Failed to allocate return: %m");
11c4c249
LP
90 goto fail;
91 }
92
93 quit = true;
94
95 } else if (sd_bus_message_is_method_call(m, NULL, NULL)) {
c784c5ce 96 r = sd_bus_message_new_method_error(
df2d202e 97 m,
151b9b96
LP
98 &reply,
99 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method."));
11c4c249 100 if (r < 0) {
da927ba9 101 log_error_errno(r, "Failed to allocate return: %m");
11c4c249
LP
102 goto fail;
103 }
104 }
105
106 if (reply) {
107 r = sd_bus_send(bus, reply, NULL);
108 if (r < 0) {
da927ba9 109 log_error_errno(r, "Failed to send reply: %m");
11c4c249
LP
110 goto fail;
111 }
112 }
113 }
114
115 r = 0;
116
117fail:
118 if (bus) {
119 sd_bus_flush(bus);
120 sd_bus_unref(bus);
121 }
122
123 return INT_TO_PTR(r);
124}
125
126static int client(struct context *c) {
127 _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
128 _cleanup_bus_unref_ sd_bus *bus = NULL;
c784c5ce 129 sd_bus_error error = SD_BUS_ERROR_NULL;
11c4c249
LP
130 int r;
131
132 assert_se(sd_bus_new(&bus) >= 0);
e82c9509 133 assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
264ad849 134 assert_se(sd_bus_negotiate_fds(bus, c->client_negotiate_unix_fds) >= 0);
11c4c249
LP
135 assert_se(sd_bus_set_anonymous(bus, c->client_anonymous_auth) >= 0);
136 assert_se(sd_bus_start(bus) >= 0);
137
138 r = sd_bus_message_new_method_call(
139 bus,
151b9b96 140 &m,
11c4c249
LP
141 "org.freedesktop.systemd.test",
142 "/",
143 "org.freedesktop.systemd.test",
151b9b96 144 "Exit");
f647962d
MS
145 if (r < 0)
146 return log_error_errno(r, "Failed to allocate method call: %m");
11c4c249 147
c49b30a2 148 r = sd_bus_call(bus, m, 0, &error, &reply);
11c4c249
LP
149 if (r < 0) {
150 log_error("Failed to issue method call: %s", bus_error_message(&error, -r));
151 return r;
152 }
153
154 return 0;
155}
156
157static int test_one(bool client_negotiate_unix_fds, bool server_negotiate_unix_fds,
158 bool client_anonymous_auth, bool server_anonymous_auth) {
159
160 struct context c;
161 pthread_t s;
162 void *p;
163 int r, q;
164
165 zero(c);
166
167 assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
168
169 c.client_negotiate_unix_fds = client_negotiate_unix_fds;
170 c.server_negotiate_unix_fds = server_negotiate_unix_fds;
171 c.client_anonymous_auth = client_anonymous_auth;
172 c.server_anonymous_auth = server_anonymous_auth;
173
174 r = pthread_create(&s, NULL, server, &c);
175 if (r != 0)
176 return -r;
177
178 r = client(&c);
179
180 q = pthread_join(s, &p);
181 if (q != 0)
182 return -q;
183
184 if (r < 0)
185 return r;
186
187 if (PTR_TO_INT(p) < 0)
188 return PTR_TO_INT(p);
189
190 return 0;
191}
192
193int main(int argc, char *argv[]) {
194 int r;
195
196 r = test_one(true, true, false, false);
197 assert_se(r >= 0);
198
199 r = test_one(true, false, false, false);
200 assert_se(r >= 0);
201
202 r = test_one(false, true, false, false);
203 assert_se(r >= 0);
204
205 r = test_one(false, false, false, false);
206 assert_se(r >= 0);
207
208 r = test_one(true, true, true, true);
209 assert_se(r >= 0);
210
211 r = test_one(true, true, false, true);
212 assert_se(r >= 0);
213
214 r = test_one(true, true, true, false);
215 assert_se(r == -EPERM);
216
217 return EXIT_SUCCESS;
218}