]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/test-bus-objects.c
tmpfiles: accurately report creation results
[thirdparty/systemd.git] / src / libsystemd / sd-bus / test-bus-objects.c
CommitLineData
29ddb38f
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
22#include <assert.h>
23#include <stdlib.h>
24#include <pthread.h>
25#include <unistd.h>
26#include <fcntl.h>
27
28#include "log.h"
29#include "util.h"
30#include "macro.h"
31#include "strv.h"
32
33#include "sd-bus.h"
34#include "bus-internal.h"
35#include "bus-message.h"
40ca29a1 36#include "bus-util.h"
d311601f 37#include "bus-dump.h"
29ddb38f 38
29ddb38f
LP
39struct context {
40 int fds[2];
41 bool quit;
42 char *something;
9db76355 43 char *automatic_string_property;
adcdb374 44 uint32_t automatic_integer_property;
29ddb38f
LP
45};
46
ebcf1f97 47static int something_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
29ddb38f
LP
48 struct context *c = userdata;
49 const char *s;
50 char *n = NULL;
51 int r;
52
53 r = sd_bus_message_read(m, "s", &s);
54 assert_se(r > 0);
55
56 n = strjoin("<<<", s, ">>>", NULL);
57 assert_se(n);
58
59 free(c->something);
60 c->something = n;
61
62 log_info("AlterSomething() called, got %s, returning %s", s, n);
63
6717d473
LP
64 /* This should fail, since the return type doesn't match */
65 assert_se(sd_bus_reply_method_return(m, "u", 4711) == -ENOMSG);
66
df2d202e 67 r = sd_bus_reply_method_return(m, "s", n);
29ddb38f
LP
68 assert_se(r >= 0);
69
70 return 1;
71}
72
ebcf1f97 73static int exit_handler(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
29ddb38f
LP
74 struct context *c = userdata;
75 int r;
76
77 c->quit = true;
78
79 log_info("Exit called");
80
df2d202e 81 r = sd_bus_reply_method_return(m, "");
29ddb38f
LP
82 assert_se(r >= 0);
83
84 return 1;
85}
86
ebcf1f97 87static int get_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
29ddb38f
LP
88 struct context *c = userdata;
89 int r;
90
ebcf1f97 91 log_info("property get for %s called, returning \"%s\".", property, c->something);
29ddb38f
LP
92
93 r = sd_bus_message_append(reply, "s", c->something);
94 assert_se(r >= 0);
95
96 return 1;
97}
98
ebcf1f97 99static int set_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *value, void *userdata, sd_bus_error *error) {
29ddb38f
LP
100 struct context *c = userdata;
101 const char *s;
102 char *n;
103 int r;
104
105 log_info("property set for %s called", property);
106
107 r = sd_bus_message_read(value, "s", &s);
108 assert_se(r >= 0);
109
110 n = strdup(s);
111 assert_se(n);
112
113 free(c->something);
114 c->something = n;
115
116 return 1;
117}
118
ebcf1f97 119static int value_handler(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
29ddb38f
LP
120 _cleanup_free_ char *s = NULL;
121 const char *x;
122 int r;
123
124 assert_se(asprintf(&s, "object %p, path %s", userdata, path) >= 0);
125 r = sd_bus_message_append(reply, "s", s);
126 assert_se(r >= 0);
127
128 assert_se(x = startswith(path, "/value/"));
129
130 assert_se(PTR_TO_UINT(userdata) == 30);
131
62b5c2ae
LP
132 return 1;
133}
134
ebcf1f97 135static int notify_test(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
62b5c2ae
LP
136 int r;
137
138 assert_se(sd_bus_emit_properties_changed(bus, m->path, "org.freedesktop.systemd.ValueTest", "Value", NULL) >= 0);
139
df2d202e 140 r = sd_bus_reply_method_return(m, NULL);
62b5c2ae 141 assert_se(r >= 0);
29ddb38f
LP
142
143 return 1;
144}
145
a03e4337
LP
146static int notify_test2(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
147 int r;
148
149 assert_se(sd_bus_emit_properties_changed_strv(bus, m->path, "org.freedesktop.systemd.ValueTest", NULL) >= 0);
150
151 r = sd_bus_reply_method_return(m, NULL);
152 assert_se(r >= 0);
153
154 return 1;
155}
156
ebcf1f97 157static int emit_interfaces_added(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
4be39163
LP
158 int r;
159
160 assert_se(sd_bus_emit_interfaces_added(bus, m->path, "org.freedesktop.systemd.test", NULL) >= 0);
161
df2d202e 162 r = sd_bus_reply_method_return(m, NULL);
4be39163
LP
163 assert_se(r >= 0);
164
165 return 1;
166}
167
ebcf1f97 168static int emit_interfaces_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
4be39163
LP
169 int r;
170
171 assert_se(sd_bus_emit_interfaces_removed(bus, m->path, "org.freedesktop.systemd.test", NULL) >= 0);
172
df2d202e 173 r = sd_bus_reply_method_return(m, NULL);
4be39163
LP
174 assert_se(r >= 0);
175
176 return 1;
177}
178
d95eb43e
DH
179static int emit_object_added(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
180 int r;
181
182 assert_se(sd_bus_emit_object_added(bus, m->path) >= 0);
183
184 r = sd_bus_reply_method_return(m, NULL);
185 assert_se(r >= 0);
186
187 return 1;
188}
189
190static int emit_object_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
191 int r;
192
193 assert_se(sd_bus_emit_object_removed(bus, m->path) >= 0);
194
195 r = sd_bus_reply_method_return(m, NULL);
196 assert_se(r >= 0);
197
198 return 1;
199}
200
29ddb38f
LP
201static const sd_bus_vtable vtable[] = {
202 SD_BUS_VTABLE_START(0),
adcdb374
LP
203 SD_BUS_METHOD("AlterSomething", "s", "s", something_handler, 0),
204 SD_BUS_METHOD("Exit", "", "", exit_handler, 0),
29ddb38f 205 SD_BUS_WRITABLE_PROPERTY("Something", "s", get_handler, set_handler, 0, 0),
9db76355
LP
206 SD_BUS_WRITABLE_PROPERTY("AutomaticStringProperty", "s", NULL, NULL, offsetof(struct context, automatic_string_property), 0),
207 SD_BUS_WRITABLE_PROPERTY("AutomaticIntegerProperty", "u", NULL, NULL, offsetof(struct context, automatic_integer_property), 0),
4be39163
LP
208 SD_BUS_METHOD("NoOperation", NULL, NULL, NULL, 0),
209 SD_BUS_METHOD("EmitInterfacesAdded", NULL, NULL, emit_interfaces_added, 0),
210 SD_BUS_METHOD("EmitInterfacesRemoved", NULL, NULL, emit_interfaces_removed, 0),
d95eb43e
DH
211 SD_BUS_METHOD("EmitObjectAdded", NULL, NULL, emit_object_added, 0),
212 SD_BUS_METHOD("EmitObjectRemoved", NULL, NULL, emit_object_removed, 0),
29ddb38f
LP
213 SD_BUS_VTABLE_END
214};
215
216static const sd_bus_vtable vtable2[] = {
217 SD_BUS_VTABLE_START(0),
adcdb374 218 SD_BUS_METHOD("NotifyTest", "", "", notify_test, 0),
a03e4337 219 SD_BUS_METHOD("NotifyTest2", "", "", notify_test2, 0),
62b5c2ae 220 SD_BUS_PROPERTY("Value", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
a03e4337
LP
221 SD_BUS_PROPERTY("Value2", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
222 SD_BUS_PROPERTY("Value3", "s", value_handler, 10, SD_BUS_VTABLE_PROPERTY_CONST),
223 SD_BUS_PROPERTY("Value4", "s", value_handler, 10, 0),
29ddb38f
LP
224 SD_BUS_VTABLE_END
225};
226
19befb2d 227static int enumerator_callback(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) {
29ddb38f
LP
228
229 if (object_path_startswith("/value", path))
230 assert_se(*nodes = strv_new("/value/a", "/value/b", "/value/c", NULL));
231
232 return 1;
233}
234
235static void *server(void *p) {
236 struct context *c = p;
237 sd_bus *bus = NULL;
238 sd_id128_t id;
239 int r;
240
241 c->quit = false;
242
243 assert_se(sd_id128_randomize(&id) >= 0);
244
245 assert_se(sd_bus_new(&bus) >= 0);
246 assert_se(sd_bus_set_fd(bus, c->fds[0], c->fds[0]) >= 0);
247 assert_se(sd_bus_set_server(bus, 1, id) >= 0);
248
19befb2d
LP
249 assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test", vtable, c) >= 0);
250 assert_se(sd_bus_add_object_vtable(bus, NULL, "/foo", "org.freedesktop.systemd.test2", vtable, c) >= 0);
251 assert_se(sd_bus_add_fallback_vtable(bus, NULL, "/value", "org.freedesktop.systemd.ValueTest", vtable2, NULL, UINT_TO_PTR(20)) >= 0);
252 assert_se(sd_bus_add_node_enumerator(bus, NULL, "/value", enumerator_callback, NULL) >= 0);
253 assert_se(sd_bus_add_object_manager(bus, NULL, "/value") >= 0);
29ddb38f
LP
254
255 assert_se(sd_bus_start(bus) >= 0);
256
257 log_error("Entering event loop on server");
258
259 while (!c->quit) {
260 log_error("Loop!");
261
262 r = sd_bus_process(bus, NULL);
263 if (r < 0) {
da927ba9 264 log_error_errno(r, "Failed to process requests: %m");
29ddb38f
LP
265 goto fail;
266 }
267
268 if (r == 0) {
269 r = sd_bus_wait(bus, (uint64_t) -1);
270 if (r < 0) {
da927ba9 271 log_error_errno(r, "Failed to wait: %m");
29ddb38f
LP
272 goto fail;
273 }
274
275 continue;
276 }
277 }
278
279 r = 0;
280
281fail:
282 if (bus) {
283 sd_bus_flush(bus);
284 sd_bus_unref(bus);
285 }
286
287 return INT_TO_PTR(r);
288}
289
290static int client(struct context *c) {
291 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
292 _cleanup_bus_unref_ sd_bus *bus = NULL;
293 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
294 const char *s;
295 int r;
296
297 assert_se(sd_bus_new(&bus) >= 0);
298 assert_se(sd_bus_set_fd(bus, c->fds[1], c->fds[1]) >= 0);
299 assert_se(sd_bus_start(bus) >= 0);
300
43a43f50
LP
301 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "NoOperation", &error, NULL, NULL);
302 assert_se(r >= 0);
303
29ddb38f
LP
304 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "s", "hallo");
305 assert_se(r >= 0);
306
307 r = sd_bus_message_read(reply, "s", &s);
308 assert_se(r >= 0);
309 assert_se(streq(s, "<<<hallo>>>"));
310
311 sd_bus_message_unref(reply);
312 reply = NULL;
313
314 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Doesntexist", &error, &reply, "");
315 assert_se(r < 0);
40ca29a1 316 assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
29ddb38f
LP
317
318 sd_bus_error_free(&error);
319
320 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AlterSomething", &error, &reply, "as", 1, "hallo");
321 assert_se(r < 0);
40ca29a1 322 assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_INVALID_ARGS));
29ddb38f
LP
323
324 sd_bus_error_free(&error);
325
326 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
327 assert_se(r >= 0);
328
329 r = sd_bus_message_read(reply, "s", &s);
330 assert_se(r >= 0);
331 assert_se(streq(s, "<<<hallo>>>"));
332
333 sd_bus_message_unref(reply);
334 reply = NULL;
335
336 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, "s", "test");
337 assert_se(r >= 0);
338
339 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Something", &error, &reply, "s");
340 assert_se(r >= 0);
341
342 r = sd_bus_message_read(reply, "s", &s);
343 assert_se(r >= 0);
344 assert_se(streq(s, "test"));
345
346 sd_bus_message_unref(reply);
347 reply = NULL;
348
9db76355
LP
349 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticIntegerProperty", &error, "u", 815);
350 assert_se(r >= 0);
351
352 assert_se(c->automatic_integer_property == 815);
353
354 r = sd_bus_set_property(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "AutomaticStringProperty", &error, "s", "Du Dödel, Du!");
355 assert_se(r >= 0);
356
357 assert_se(streq(c->automatic_string_property, "Du Dödel, Du!"));
358
29ddb38f 359 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 360 assert_se(r >= 0);
29ddb38f
LP
361
362 r = sd_bus_message_read(reply, "s", &s);
363 assert_se(r >= 0);
364 fputs(s, stdout);
365
366 sd_bus_message_unref(reply);
367 reply = NULL;
368
369 r = sd_bus_get_property(bus, "org.freedesktop.systemd.test", "/value/xuzz", "org.freedesktop.systemd.ValueTest", "Value", &error, &reply, "s");
370 assert_se(r >= 0);
371
372 r = sd_bus_message_read(reply, "s", &s);
373 assert_se(r >= 0);
374 log_info("read %s", s);
375
376 sd_bus_message_unref(reply);
377 reply = NULL;
378
379 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 380 assert_se(r >= 0);
29ddb38f
LP
381
382 r = sd_bus_message_read(reply, "s", &s);
383 assert_se(r >= 0);
384 fputs(s, stdout);
385
386 sd_bus_message_unref(reply);
387 reply = NULL;
388
389 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 390 assert_se(r >= 0);
29ddb38f
LP
391
392 r = sd_bus_message_read(reply, "s", &s);
393 assert_se(r >= 0);
394 fputs(s, stdout);
395
396 sd_bus_message_unref(reply);
397 reply = NULL;
398
399 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Introspectable", "Introspect", &error, &reply, "");
5d12cc3e 400 assert_se(r >= 0);
29ddb38f
LP
401
402 r = sd_bus_message_read(reply, "s", &s);
403 assert_se(r >= 0);
404 fputs(s, stdout);
405
406 sd_bus_message_unref(reply);
407 reply = NULL;
408
409 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "");
5d12cc3e 410 assert_se(r >= 0);
29ddb38f 411
d55192ad 412 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
29ddb38f
LP
413
414 sd_bus_message_unref(reply);
415 reply = NULL;
416
417 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.DBus.Properties", "GetAll", &error, &reply, "s", "org.freedesktop.systemd.ValueTest2");
418 assert_se(r < 0);
40ca29a1 419 assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_INTERFACE));
29ddb38f
LP
420 sd_bus_error_free(&error);
421
5d12cc3e
LP
422 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
423 assert_se(r < 0);
40ca29a1 424 assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_METHOD));
5d12cc3e
LP
425 sd_bus_error_free(&error);
426
427 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value", "org.freedesktop.DBus.ObjectManager", "GetManagedObjects", &error, &reply, "");
428 assert_se(r >= 0);
429
d55192ad 430 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
5d12cc3e
LP
431
432 sd_bus_message_unref(reply);
433 reply = NULL;
434
62b5c2ae
LP
435 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest", &error, NULL, "");
436 assert_se(r >= 0);
437
438 r = sd_bus_process(bus, &reply);
439 assert_se(r > 0);
440
441 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
d55192ad 442 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
a03e4337
LP
443
444 sd_bus_message_unref(reply);
445 reply = NULL;
446
447 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/value/a", "org.freedesktop.systemd.ValueTest", "NotifyTest2", &error, NULL, "");
448 assert_se(r >= 0);
449
450 r = sd_bus_process(bus, &reply);
451 assert_se(r > 0);
452
453 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.Properties", "PropertiesChanged"));
d55192ad 454 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
4be39163
LP
455
456 sd_bus_message_unref(reply);
457 reply = NULL;
458
459 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesAdded", &error, NULL, "");
460 assert_se(r >= 0);
461
462 r = sd_bus_process(bus, &reply);
463 assert_se(r > 0);
464
465 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
d55192ad 466 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
4be39163
LP
467
468 sd_bus_message_unref(reply);
469 reply = NULL;
470
471 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitInterfacesRemoved", &error, NULL, "");
472 assert_se(r >= 0);
473
474 r = sd_bus_process(bus, &reply);
475 assert_se(r > 0);
476
477 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
d55192ad 478 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
d95eb43e
DH
479
480 sd_bus_message_unref(reply);
481 reply = NULL;
482
483 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectAdded", &error, NULL, "");
484 assert_se(r >= 0);
485
486 r = sd_bus_process(bus, &reply);
487 assert_se(r > 0);
488
489 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesAdded"));
490 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
491
492 sd_bus_message_unref(reply);
493 reply = NULL;
494
495 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "EmitObjectRemoved", &error, NULL, "");
496 assert_se(r >= 0);
497
498 r = sd_bus_process(bus, &reply);
499 assert_se(r > 0);
500
501 assert_se(sd_bus_message_is_signal(reply, "org.freedesktop.DBus.ObjectManager", "InterfacesRemoved"));
502 bus_message_dump(reply, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
62b5c2ae
LP
503
504 sd_bus_message_unref(reply);
505 reply = NULL;
506
29ddb38f
LP
507 r = sd_bus_call_method(bus, "org.freedesktop.systemd.test", "/foo", "org.freedesktop.systemd.test", "Exit", &error, NULL, "");
508 assert_se(r >= 0);
509
510 sd_bus_flush(bus);
511
512 return 0;
513}
514
515int main(int argc, char *argv[]) {
ebcf1f97 516 struct context c = {};
29ddb38f
LP
517 pthread_t s;
518 void *p;
519 int r, q;
520
521 zero(c);
522
adcdb374 523 c.automatic_integer_property = 4711;
9db76355 524 assert_se(c.automatic_string_property = strdup("dudeldu"));
adcdb374 525
29ddb38f
LP
526 assert_se(socketpair(AF_UNIX, SOCK_STREAM, 0, c.fds) >= 0);
527
528 r = pthread_create(&s, NULL, server, &c);
529 if (r != 0)
530 return -r;
531
532 r = client(&c);
533
534 q = pthread_join(s, &p);
535 if (q != 0)
536 return -q;
537
538 if (r < 0)
539 return r;
540
541 if (PTR_TO_INT(p) < 0)
542 return PTR_TO_INT(p);
543
544 free(c.something);
9db76355 545 free(c.automatic_string_property);
29ddb38f
LP
546
547 return EXIT_SUCCESS;
548}