chiark / gitweb /
bus: calculate iovec for messages only when we need it
[elogind.git] / src / libsystemd-bus / bus-control.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 <stddef.h>
23 #include <errno.h>
24
25 #include "strv.h"
26
27 #include "sd-bus.h"
28 #include "bus-internal.h"
29 #include "bus-message.h"
30 #include "bus-control.h"
31
32 int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
33         int r;
34
35         if (!bus)
36                 return -EINVAL;
37         if (!unique)
38                 return -EINVAL;
39
40         r = bus_ensure_running(bus);
41         if (r < 0)
42                 return r;
43
44         *unique = bus->unique_name;
45         return 0;
46 }
47
48 int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
49         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
50         uint32_t ret;
51         int r;
52
53         if (!bus)
54                 return -EINVAL;
55         if (!name)
56                 return -EINVAL;
57
58         r = sd_bus_call_method(
59                         bus,
60                         "org.freedesktop.DBus",
61                         "/",
62                         "org.freedesktop.DBus",
63                         "RequestName",
64                         NULL,
65                         &reply,
66                         "su",
67                         name,
68                         flags);
69         if (r < 0)
70                 return r;
71
72         r = sd_bus_message_read(reply, "u", &ret);
73         if (r < 0)
74                 return r;
75
76         return ret;
77 }
78
79 int sd_bus_release_name(sd_bus *bus, const char *name) {
80         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
81         uint32_t ret;
82         int r;
83
84         if (!bus)
85                 return -EINVAL;
86         if (!name)
87                 return -EINVAL;
88
89         r = sd_bus_call_method(
90                         bus,
91                         "org.freedesktop.DBus",
92                         "/",
93                         "org.freedesktop.DBus",
94                         "ReleaseName",
95                         NULL,
96                         &reply,
97                         "s",
98                         name);
99         if (r < 0)
100                 return r;
101
102         r = sd_bus_message_read(reply, "u", &ret);
103         if (r < 0)
104                 return r;
105
106         return ret;
107 }
108
109 int sd_bus_list_names(sd_bus *bus, char ***l) {
110         _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
111         char **x = NULL;
112         int r;
113
114         if (!bus)
115                 return -EINVAL;
116         if (!l)
117                 return -EINVAL;
118
119         r = sd_bus_call_method(
120                         bus,
121                         "org.freedesktop.DBus",
122                         "/",
123                         "org.freedesktop.DBus",
124                         "ListNames",
125                         NULL,
126                         &reply1,
127                         NULL);
128         if (r < 0)
129                 return r;
130
131         r = sd_bus_call_method(
132                         bus,
133                         "org.freedesktop.DBus",
134                         "/",
135                         "org.freedesktop.DBus",
136                         "ListActivatableNames",
137                         NULL,
138                         &reply2,
139                         NULL);
140         if (r < 0)
141                 return r;
142
143         r = bus_message_read_strv_extend(reply1, &x);
144         if (r < 0) {
145                 strv_free(x);
146                 return r;
147         }
148
149         r = bus_message_read_strv_extend(reply2, &x);
150         if (r < 0) {
151                 strv_free(x);
152                 return r;
153         }
154
155         *l = strv_uniq(x);
156         return 0;
157 }
158
159 int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner) {
160         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
161         const char *found;
162         int r;
163
164         if (!bus)
165                 return -EINVAL;
166         if (!name)
167                 return -EINVAL;
168
169         r = sd_bus_call_method(
170                         bus,
171                         "org.freedesktop.DBus",
172                         "/",
173                         "org.freedesktop.DBus",
174                         "GetNameOwner",
175                         NULL,
176                         &reply,
177                         "s",
178                         name);
179         if (r < 0)
180                 return r;
181
182         r = sd_bus_message_read(reply, "s", &found);
183         if (r < 0)
184                 return r;
185
186         if (owner) {
187                 char *t;
188
189                 t = strdup(found);
190                 if (!t)
191                         return -ENOMEM;
192
193                 *owner = t;
194         }
195
196         return 0;
197 }
198
199 int sd_bus_get_owner_uid(sd_bus *bus, const char *name, uid_t *uid) {
200         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
201         uint32_t u;
202         int r;
203
204         if (!bus)
205                 return -EINVAL;
206         if (!name)
207                 return -EINVAL;
208         if (!uid)
209                 return -EINVAL;
210
211         r = sd_bus_call_method(
212                         bus,
213                         "org.freedesktop.DBus",
214                         "/",
215                         "org.freedesktop.DBus",
216                         "GetConnectionUnixUser",
217                         NULL,
218                         &reply,
219                         "s",
220                         name);
221         if (r < 0)
222                 return r;
223
224         r = sd_bus_message_read(reply, "u", &u);
225         if (r < 0)
226                 return r;
227
228         *uid = (uid_t) u;
229         return 0;
230 }
231
232 int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) {
233         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
234         uint32_t u;
235         int r;
236
237         if (!bus)
238                 return -EINVAL;
239         if (!name)
240                 return -EINVAL;
241         if (!pid)
242                 return -EINVAL;
243
244         r = sd_bus_call_method(
245                         bus,
246                         "org.freedesktop.DBus",
247                         "/",
248                         "org.freedesktop.DBus",
249                         "GetConnectionUnixProcessID",
250                         NULL,
251                         &reply,
252                         "s",
253                         name);
254         if (r < 0)
255                 return r;
256
257         r = sd_bus_message_read(reply, "u", &u);
258         if (r < 0)
259                 return r;
260
261         if (u == 0)
262                 return -EIO;
263
264         *pid = (uid_t) u;
265         return 0;
266 }
267
268 int bus_add_match_internal(sd_bus *bus, const char *match) {
269         assert(bus);
270         assert(match);
271
272         return sd_bus_call_method(
273                         bus,
274                         "org.freedesktop.DBus",
275                         "/",
276                         "org.freedesktop.DBus",
277                         "AddMatch",
278                         NULL,
279                         NULL,
280                         "s",
281                         match);
282 }
283
284 int bus_remove_match_internal(sd_bus *bus, const char *match) {
285         assert(bus);
286         assert(match);
287
288         return sd_bus_call_method(
289                         bus,
290                         "org.freedesktop.DBus",
291                         "/",
292                         "org.freedesktop.DBus",
293                         "RemoveMatch",
294                         NULL,
295                         NULL,
296                         "s",
297                         match);
298 }