chiark / gitweb /
event: clear pending-state when re-arming timers
[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 #include "bus-type.h"
27
28 _public_ int sd_bus_emit_signal(
29                 sd_bus *bus,
30                 const char *path,
31                 const char *interface,
32                 const char *member,
33                 const char *types, ...) {
34
35         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
36         int r;
37
38         assert_return(bus, -EINVAL);
39         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
40         assert_return(!bus_pid_changed(bus), -ECHILD);
41
42         r = sd_bus_message_new_signal(bus, path, interface, member, &m);
43         if (r < 0)
44                 return r;
45
46         if (!isempty(types)) {
47                 va_list ap;
48
49                 va_start(ap, types);
50                 r = bus_message_append_ap(m, types, ap);
51                 va_end(ap);
52                 if (r < 0)
53                         return r;
54         }
55
56         return sd_bus_send(bus, m, NULL);
57 }
58
59 _public_ int sd_bus_call_method(
60                 sd_bus *bus,
61                 const char *destination,
62                 const char *path,
63                 const char *interface,
64                 const char *member,
65                 sd_bus_error *error,
66                 sd_bus_message **reply,
67                 const char *types, ...) {
68
69         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
70         int r;
71
72         assert_return(bus, -EINVAL);
73         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
74         assert_return(!bus_pid_changed(bus), -ECHILD);
75
76         r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
77         if (r < 0)
78                 return r;
79
80         if (!isempty(types)) {
81                 va_list ap;
82
83                 va_start(ap, types);
84                 r = bus_message_append_ap(m, types, ap);
85                 va_end(ap);
86                 if (r < 0)
87                         return r;
88         }
89
90         return sd_bus_call(bus, m, 0, error, reply);
91 }
92
93 _public_ int sd_bus_reply_method_return(
94                 sd_bus *bus,
95                 sd_bus_message *call,
96                 const char *types, ...) {
97
98         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
99         int r;
100
101         assert_return(bus, -EINVAL);
102         assert_return(call, -EINVAL);
103         assert_return(call->sealed, -EPERM);
104         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
105         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
106         assert_return(!bus_pid_changed(bus), -ECHILD);
107
108         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
109                 return 0;
110
111         r = sd_bus_message_new_method_return(bus, call, &m);
112         if (r < 0)
113                 return r;
114
115         if (!isempty(types)) {
116                 va_list ap;
117
118                 va_start(ap, types);
119                 r = bus_message_append_ap(m, types, ap);
120                 va_end(ap);
121                 if (r < 0)
122                         return r;
123         }
124
125         return sd_bus_send(bus, m, NULL);
126 }
127
128 _public_ int sd_bus_reply_method_error(
129                 sd_bus *bus,
130                 sd_bus_message *call,
131                 const sd_bus_error *e) {
132
133         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
134         int r;
135
136         assert_return(bus, -EINVAL);
137         assert_return(call, -EINVAL);
138         assert_return(call->sealed, -EPERM);
139         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
140         assert_return(sd_bus_error_is_set(e), -EINVAL);
141         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
142         assert_return(!bus_pid_changed(bus), -ECHILD);
143
144         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
145                 return 0;
146
147         r = sd_bus_message_new_method_error(bus, call, e, &m);
148         if (r < 0)
149                 return r;
150
151         return sd_bus_send(bus, m, NULL);
152 }
153
154 _public_ int sd_bus_reply_method_errorf(
155                 sd_bus *bus,
156                 sd_bus_message *call,
157                 const char *name,
158                 const char *format,
159                 ...) {
160
161         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
162         va_list ap;
163         int r;
164
165         assert_return(bus, -EINVAL);
166         assert_return(call, -EINVAL);
167         assert_return(call->sealed, -EPERM);
168         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
169         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
170         assert_return(!bus_pid_changed(bus), -ECHILD);
171
172         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
173                 return 0;
174
175         va_start(ap, format);
176         r = bus_error_setfv(&error, name, format, ap);
177         va_end(ap);
178
179         if (r < 0)
180                 return r;
181
182         return sd_bus_reply_method_error(bus, call, &error);
183 }
184
185 _public_ int sd_bus_reply_method_errno(
186                 sd_bus *bus,
187                 sd_bus_message *call,
188                 int error,
189                 const sd_bus_error *p) {
190
191         _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
192
193         assert_return(bus, -EINVAL);
194         assert_return(call, -EINVAL);
195         assert_return(call->sealed, -EPERM);
196         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
197         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
198         assert_return(!bus_pid_changed(bus), -ECHILD);
199
200         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
201                 return 0;
202
203         if (sd_bus_error_is_set(p))
204                 return sd_bus_reply_method_error(bus, call, p);
205
206         sd_bus_error_set_errno(&berror, error);
207
208         return sd_bus_reply_method_error(bus, call, &berror);
209 }
210
211 _public_ int sd_bus_reply_method_errnof(
212                 sd_bus *bus,
213                 sd_bus_message *call,
214                 int error,
215                 const char *format,
216                 ...) {
217
218         _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
219         va_list ap;
220
221         assert_return(bus, -EINVAL);
222         assert_return(call, -EINVAL);
223         assert_return(call->sealed, -EPERM);
224         assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
225         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
226         assert_return(!bus_pid_changed(bus), -ECHILD);
227
228         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
229                 return 0;
230
231         va_start(ap, format);
232         bus_error_set_errnofv(&berror, error, format, ap);
233         va_end(ap);
234
235         return sd_bus_reply_method_error(bus, call, &berror);
236 }
237
238 _public_ int sd_bus_get_property(
239                 sd_bus *bus,
240                 const char *destination,
241                 const char *path,
242                 const char *interface,
243                 const char *member,
244                 sd_bus_error *error,
245                 sd_bus_message **reply,
246                 const char *type) {
247
248         sd_bus_message *rep = NULL;
249         int r;
250
251         assert_return(bus, -EINVAL);
252         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
253         assert_return(member_name_is_valid(member), -EINVAL);
254         assert_return(reply, -EINVAL);
255         assert_return(signature_is_single(type, false), -EINVAL);
256         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
257         assert_return(!bus_pid_changed(bus), -ECHILD);
258
259         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
260         if (r < 0)
261                 return r;
262
263         r = sd_bus_message_enter_container(rep, 'v', type);
264         if (r < 0) {
265                 sd_bus_message_unref(rep);
266                 return r;
267         }
268
269         *reply = rep;
270         return 0;
271 }
272
273 _public_ int sd_bus_get_property_trivial(
274                 sd_bus *bus,
275                 const char *destination,
276                 const char *path,
277                 const char *interface,
278                 const char *member,
279                 sd_bus_error *error,
280                 char type, void *ptr) {
281
282         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
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(bus_type_is_trivial(type), -EINVAL);
289         assert_return(ptr, -EINVAL);
290         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
291         assert_return(!bus_pid_changed(bus), -ECHILD);
292
293         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
294         if (r < 0)
295                 return r;
296
297         r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
298         if (r < 0)
299                 return r;
300
301         r = sd_bus_message_read_basic(reply, type, ptr);
302         if (r < 0)
303                 return r;
304
305         return 0;
306 }
307
308 _public_ int sd_bus_get_property_string(
309                 sd_bus *bus,
310                 const char *destination,
311                 const char *path,
312                 const char *interface,
313                 const char *member,
314                 sd_bus_error *error,
315                 char **ret) {
316
317         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
318         const char *s;
319         char *n;
320         int r;
321
322         assert_return(bus, -EINVAL);
323         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
324         assert_return(member_name_is_valid(member), -EINVAL);
325         assert_return(ret, -EINVAL);
326         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
327         assert_return(!bus_pid_changed(bus), -ECHILD);
328
329         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
330         if (r < 0)
331                 return r;
332
333         r = sd_bus_message_enter_container(reply, 'v', "s");
334         if (r < 0)
335                 return r;
336
337         r = sd_bus_message_read_basic(reply, 's', &s);
338         if (r < 0)
339                 return r;
340
341         n = strdup(s);
342         if (!n)
343                 return -ENOMEM;
344
345         *ret = n;
346         return 0;
347 }
348
349 _public_ int sd_bus_get_property_strv(
350                 sd_bus *bus,
351                 const char *destination,
352                 const char *path,
353                 const char *interface,
354                 const char *member,
355                 sd_bus_error *error,
356                 char ***ret) {
357
358         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
359         int r;
360
361         assert_return(bus, -EINVAL);
362         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
363         assert_return(member_name_is_valid(member), -EINVAL);
364         assert_return(ret, -EINVAL);
365         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
366         assert_return(!bus_pid_changed(bus), -ECHILD);
367
368         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
369         if (r < 0)
370                 return r;
371
372         r = sd_bus_message_enter_container(reply, 'v', NULL);
373         if (r < 0)
374                 return r;
375
376         r = sd_bus_message_read_strv(reply, ret);
377         if (r < 0)
378                 return r;
379
380         return 0;
381 }
382
383 _public_ int sd_bus_set_property(
384                 sd_bus *bus,
385                 const char *destination,
386                 const char *path,
387                 const char *interface,
388                 const char *member,
389                 sd_bus_error *error,
390                 const char *type, ...) {
391
392         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
393         va_list ap;
394         int r;
395
396         assert_return(bus, -EINVAL);
397         assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
398         assert_return(member_name_is_valid(member), -EINVAL);
399         assert_return(signature_is_single(type, false), -EINVAL);
400         assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
401         assert_return(!bus_pid_changed(bus), -ECHILD);
402
403         r = sd_bus_message_new_method_call(bus, destination, path, "org.freedesktop.DBus.Properties", "Set", &m);
404         if (r < 0)
405                 return r;
406
407         r = sd_bus_message_append(m, "ss", strempty(interface), member);
408         if (r < 0)
409                 return r;
410
411         r = sd_bus_message_open_container(m, 'v', type);
412         if (r < 0)
413                 return r;
414
415         va_start(ap, type);
416         r = bus_message_append_ap(m, type, ap);
417         va_end(ap);
418         if (r < 0)
419                 return r;
420
421         r = sd_bus_message_close_container(m);
422         if (r < 0)
423                 return r;
424
425         return sd_bus_call(bus, m, 0, error, NULL);
426 }