]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-convenience.c
bus: split up overly long sd-bus.c into three files
[thirdparty/systemd.git] / src / libsystemd-bus / bus-convenience.c
CommitLineData
992c052c
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 "bus-internal.h"
23#include "bus-message.h"
24#include "bus-signature.h"
25
26int 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
60int 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
98int 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
139int 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
172int 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
201int 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
237int 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}