chiark / gitweb /
bus: split up overly long sd-bus.c into three files
[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
26 int sd_bus_emit_signal(
27                 sd_bus *bus,
28                 const char *path,
29                 const char *interface,
30                 const char *member,
31                 const char *types, ...) {
32
33         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
34         int r;
35
36         if (!bus)
37                 return -EINVAL;
38         if (!BUS_IS_OPEN(bus->state))
39                 return -ENOTCONN;
40         if (bus_pid_changed(bus))
41                 return -ECHILD;
42
43         r = sd_bus_message_new_signal(bus, path, interface, member, &m);
44         if (r < 0)
45                 return r;
46
47         if (!isempty(types)) {
48                 va_list ap;
49
50                 va_start(ap, types);
51                 r = bus_message_append_ap(m, types, ap);
52                 va_end(ap);
53                 if (r < 0)
54                         return r;
55         }
56
57         return sd_bus_send(bus, m, NULL);
58 }
59
60 int sd_bus_call_method(
61                 sd_bus *bus,
62                 const char *destination,
63                 const char *path,
64                 const char *interface,
65                 const char *member,
66                 sd_bus_error *error,
67                 sd_bus_message **reply,
68                 const char *types, ...) {
69
70         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
71         int r;
72
73         if (!bus)
74
75                 return -EINVAL;
76         if (!BUS_IS_OPEN(bus->state))
77                 return -ENOTCONN;
78         if (bus_pid_changed(bus))
79                 return -ECHILD;
80
81         r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
82         if (r < 0)
83                 return r;
84
85         if (!isempty(types)) {
86                 va_list ap;
87
88                 va_start(ap, types);
89                 r = bus_message_append_ap(m, types, ap);
90                 va_end(ap);
91                 if (r < 0)
92                         return r;
93         }
94
95         return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
96 }
97
98 int sd_bus_reply_method_return(
99                 sd_bus *bus,
100                 sd_bus_message *call,
101                 const char *types, ...) {
102
103         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
104         int r;
105
106         if (!bus)
107                 return -EINVAL;
108         if (!call)
109                 return -EINVAL;
110         if (!call->sealed)
111                 return -EPERM;
112         if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
113                 return -EINVAL;
114         if (!BUS_IS_OPEN(bus->state))
115                 return -ENOTCONN;
116         if (bus_pid_changed(bus))
117                 return -ECHILD;
118
119         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
120                 return 0;
121
122         r = sd_bus_message_new_method_return(bus, call, &m);
123         if (r < 0)
124                 return r;
125
126         if (!isempty(types)) {
127                 va_list ap;
128
129                 va_start(ap, types);
130                 r = bus_message_append_ap(m, types, ap);
131                 va_end(ap);
132                 if (r < 0)
133                         return r;
134         }
135
136         return sd_bus_send(bus, m, NULL);
137 }
138
139 int sd_bus_reply_method_error(
140                 sd_bus *bus,
141                 sd_bus_message *call,
142                 const sd_bus_error *e) {
143
144         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
145         int r;
146
147         if (!bus)
148                 return -EINVAL;
149         if (!call)
150                 return -EINVAL;
151         if (!call->sealed)
152                 return -EPERM;
153         if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
154                 return -EINVAL;
155         if (!sd_bus_error_is_set(e))
156                 return -EINVAL;
157         if (!BUS_IS_OPEN(bus->state))
158                 return -ENOTCONN;
159         if (bus_pid_changed(bus))
160                 return -ECHILD;
161
162         if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
163                 return 0;
164
165         r = sd_bus_message_new_method_error(bus, call, e, &m);
166         if (r < 0)
167                 return r;
168
169         return sd_bus_send(bus, m, NULL);
170 }
171
172 int sd_bus_reply_method_errorf(
173                 sd_bus *bus,
174                 sd_bus_message *call,
175                 const char *name,
176                 const char *format,
177                 ...) {
178
179         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
180         va_list ap;
181         int r;
182
183         error.name = strdup(name);
184         if (!error.name)
185                 return -ENOMEM;
186
187         error.need_free = true;
188
189         if (format) {
190                 va_start(ap, format);
191                 r = vasprintf((char**) &error.message, format, ap);
192                 va_end(ap);
193
194                 if (r < 0)
195                         return -ENOMEM;
196         }
197
198         return sd_bus_reply_method_error(bus, call, &error);
199 }
200
201 int sd_bus_get_property(
202                 sd_bus *bus,
203                 const char *destination,
204                 const char *path,
205                 const char *interface,
206                 const char *member,
207                 sd_bus_error *error,
208                 sd_bus_message **reply,
209                 const char *type) {
210
211         sd_bus_message *rep = NULL;
212         int r;
213
214         if (interface && !interface_name_is_valid(interface))
215                 return -EINVAL;
216         if (!member_name_is_valid(member))
217                 return -EINVAL;
218         if (!signature_is_single(type, false))
219                 return -EINVAL;
220         if (!reply)
221                 return -EINVAL;
222
223         r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
224         if (r < 0)
225                 return r;
226
227         r = sd_bus_message_enter_container(rep, 'v', type);
228         if (r < 0) {
229                 sd_bus_message_unref(rep);
230                 return r;
231         }
232
233         *reply = rep;
234         return 0;
235 }
236
237 int sd_bus_set_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                 const char *type, ...) {
245
246         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
247         va_list ap;
248         int r;
249
250         if (interface && !interface_name_is_valid(interface))
251                 return -EINVAL;
252         if (!member_name_is_valid(member))
253                 return -EINVAL;
254         if (!signature_is_single(type, false))
255                 return -EINVAL;
256
257         r = sd_bus_message_new_method_call(bus, destination, path, "org.freedesktop.DBus.Properties", "Set", &m);
258         if (r < 0)
259                 return r;
260
261         r = sd_bus_message_append(m, "ss", strempty(interface), member);
262         if (r < 0)
263                 return r;
264
265         r = sd_bus_message_open_container(m, 'v', type);
266         if (r < 0)
267                 return r;
268
269         va_start(ap, type);
270         r = bus_message_append_ap(m, type, ap);
271         va_end(ap);
272         if (r < 0)
273                 return r;
274
275         r = sd_bus_message_close_container(m);
276         if (r < 0)
277                 return r;
278
279         return sd_bus_send_with_reply_and_block(bus, m, 0, error, NULL);
280 }