chiark / gitweb /
timedated: use libsystemd-bus instead of libdbus for bus communication
[elogind.git] / src / libsystemd-bus / bus-convenience.c
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 "bus-internal.h"
23 #include "bus-message.h"
24 #include "bus-signature.h"
25 #include "bus-util.h"
26
27 int sd_bus_emit_signal(
28                 sd_bus *bus,
29                 const char *path,
30                 const char *interface,
31                 const char *member,
32                 const char *types, ...) {
33
34         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
35         int r;
36
37         assert_return(bus, -EINVAL);
38         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
39         assert_return(!bus_pid_changed(bus), -ECHILD);
40
41         r = sd_bus_message_new_signal(bus, path, interface, member, &m);
42         if (r < 0)
43                 return r;
44
45         if (!isempty(types)) {
46                 va_list ap;
47
48                 va_start(ap, types);
49                 r = bus_message_append_ap(m, types, ap);
50                 va_end(ap);
51                 if (r < 0)
52                         return r;
53         }
54
55         return sd_bus_send(bus, m, NULL);
56 }
57
58 int sd_bus_call_method(
59                 sd_bus *bus,
60                 const char *destination,
61                 const char *path,
62                 const char *interface,
63                 const char *member,
64                 sd_bus_error *error,
65                 sd_bus_message **reply,
66                 const char *types, ...) {
67
68         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
69         int r;
70
71         assert_return(bus, -EINVAL);
72         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
73         assert_return(!bus_pid_changed(bus), -ECHILD);
74
75         r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
76         if (r < 0)
77                 return r;
78
79         if (!isempty(types)) {
80                 va_list ap;
81
82                 va_start(ap, types);
83                 r = bus_message_append_ap(m, types, ap);
84                 va_end(ap);
85                 if (r < 0)
86                         return r;
87         }
88
89         return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
90 }
91
92 int sd_bus_reply_method_return(
93                 sd_bus *bus,
94                 sd_bus_message *call,
95                 const char *types, ...) {
96
97         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
98         int r;
99
100         assert_return(bus, -EINVAL);
101         assert_return(call, -EINVAL);
102         assert_return(call->sealed, -EPERM);
103         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
104         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
105         assert_return(!bus_pid_changed(bus), -ECHILD);
106
107         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
108                 return 0;
109
110         r = sd_bus_message_new_method_return(bus, call, &m);
111         if (r < 0)
112                 return r;
113
114         if (!isempty(types)) {
115                 va_list ap;
116
117                 va_start(ap, types);
118                 r = bus_message_append_ap(m, types, ap);
119                 va_end(ap);
120                 if (r < 0)
121                         return r;
122         }
123
124         return sd_bus_send(bus, m, NULL);
125 }
126
127 int sd_bus_reply_method_error(
128                 sd_bus *bus,
129                 sd_bus_message *call,
130                 const sd_bus_error *e) {
131
132         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
133         int r;
134
135         assert_return(bus, -EINVAL);
136         assert_return(call, -EINVAL);
137         assert_return(call->sealed, -EPERM);
138         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
139         assert_return(sd_bus_error_is_set(e), -EINVAL);
140         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
141         assert_return(!bus_pid_changed(bus), -ECHILD);
142
143         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
144                 return 0;
145
146         r = sd_bus_message_new_method_error(bus, call, e, &m);
147         if (r < 0)
148                 return r;
149
150         return sd_bus_send(bus, m, NULL);
151 }
152
153 int sd_bus_reply_method_errorf(
154                 sd_bus *bus,
155                 sd_bus_message *call,
156                 const char *name,
157                 const char *format,
158                 ...) {
159
160         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
161         va_list ap;
162         int r;
163
164         assert_return(bus, -EINVAL);
165         assert_return(call, -EINVAL);
166         assert_return(call->sealed, -EPERM);
167         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
168         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
169         assert_return(!bus_pid_changed(bus), -ECHILD);
170
171         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
172                 return 0;
173
174         va_start(ap, format);
175         r = bus_error_setfv(&error, name, format, ap);
176         va_end(ap);
177
178         if (r < 0)
179                 return r;
180
181         return sd_bus_reply_method_error(bus, call, &error);
182 }
183
184 int sd_bus_reply_method_errno(
185                 sd_bus *bus,
186                 sd_bus_message *call,
187                 int error,
188                 const sd_bus_error *p) {
189
190         _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
191
192         assert_return(bus, -EINVAL);
193         assert_return(call, -EINVAL);
194         assert_return(call->sealed, -EPERM);
195         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
196         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
197         assert_return(!bus_pid_changed(bus), -ECHILD);
198
199         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
200                 return 0;
201
202         if (sd_bus_error_is_set(p))
203                 return sd_bus_reply_method_error(bus, call, p);
204
205         sd_bus_error_set_errno(&berror, error);
206
207         return sd_bus_reply_method_error(bus, call, &berror);
208 }
209
210 int sd_bus_reply_method_errnof(
211                 sd_bus *bus,
212                 sd_bus_message *call,
213                 int error,
214                 const char *format,
215                 ...) {
216
217         _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
218         va_list ap;
219
220         assert_return(bus, -EINVAL);
221         assert_return(call, -EINVAL);
222         assert_return(call->sealed, -EPERM);
223         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
224         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
225         assert_return(!bus_pid_changed(bus), -ECHILD);
226
227         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
228                 return 0;
229
230         va_start(ap, format);
231         bus_error_set_errnofv(&berror, error, format, ap);
232         va_end(ap);
233
234         return sd_bus_reply_method_error(bus, call, &berror);
235 }
236
237 int sd_bus_get_property(
238                 sd_bus *bus,
239                 const char *destination,
240                 const char *path,
241                 const char *interface,
242                 const char *member,
243                 sd_bus_error *error,
244                 sd_bus_message **reply,
245                 const char *type) {
246
247         sd_bus_message *rep = NULL;
248         int r;
249
250         assert_return(bus, -EINVAL);
251         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
252         assert_return(member_name_is_valid(member), -EINVAL);
253         assert_return(reply, -EINVAL);
254         assert_return(signature_is_single(type, false), -EINVAL);
255         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
256         assert_return(!bus_pid_changed(bus), -ECHILD);
257
258         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
259         if (r < 0)
260                 return r;
261
262         r = sd_bus_message_enter_container(rep, 'v', type);
263         if (r < 0) {
264                 sd_bus_message_unref(rep);
265                 return r;
266         }
267
268         *reply = rep;
269         return 0;
270 }
271
272 int sd_bus_set_property(
273                 sd_bus *bus,
274                 const char *destination,
275                 const char *path,
276                 const char *interface,
277                 const char *member,
278                 sd_bus_error *error,
279                 const char *type, ...) {
280
281         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
282         va_list ap;
283         int r;
284
285         assert_return(bus, -EINVAL);
286         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
287         assert_return(member_name_is_valid(member), -EINVAL);
288         assert_return(signature_is_single(type, false), -EINVAL);
289         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
290         assert_return(!bus_pid_changed(bus), -ECHILD);
291
292         r = sd_bus_message_new_method_call(bus, destination, path, "org.freedesktop.DBus.Properties", "Set", &m);
293         if (r < 0)
294                 return r;
295
296         r = sd_bus_message_append(m, "ss", strempty(interface), member);
297         if (r < 0)
298                 return r;
299
300         r = sd_bus_message_open_container(m, 'v', type);
301         if (r < 0)
302                 return r;
303
304         va_start(ap, type);
305         r = bus_message_append_ap(m, type, ap);
306         va_end(ap);
307         if (r < 0)
308                 return r;
309
310         r = sd_bus_message_close_container(m);
311         if (r < 0)
312                 return r;
313
314         return sd_bus_send_with_reply_and_block(bus, m, 0, error, NULL);
315 }