]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/bus-proxyd/synthesize.c
Merge branch 'hostnamectl-dot-v2'
[thirdparty/systemd.git] / src / bus-proxyd / synthesize.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
9
10 systemd is free software; you can redistribute it and/or modify it
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public License
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 ***/
23
24 #include <stddef.h>
25
26 #include "util.h"
27 #include "sd-bus.h"
28 #include "bus-internal.h"
29 #include "bus-message.h"
30 #include "bus-util.h"
31 #include "bus-match.h"
32 #include "synthesize.h"
33
34 int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
35 int r;
36
37 assert(b);
38 assert(m);
39
40 r = bus_message_append_sender(m, "org.freedesktop.DBus");
41 if (r < 0)
42 return r;
43
44 r = bus_seal_synthetic_message(b, m);
45 if (r < 0)
46 return r;
47
48 return sd_bus_send(b, m, NULL);
49 }
50
51 int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
52 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
53 int r;
54
55 assert(call);
56
57 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
58 return 0;
59
60 r = sd_bus_message_new_method_error(call, &m, e);
61 if (r < 0)
62 return r;
63
64 return synthetic_driver_send(call->bus, m);
65 }
66
67 int synthetic_reply_method_errorf(sd_bus_message *call, const char *name, const char *format, ...) {
68 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
69 va_list ap;
70
71 va_start(ap, format);
72 bus_error_setfv(&error, name, format, ap);
73 va_end(ap);
74
75 return synthetic_reply_method_error(call, &error);
76 }
77
78 int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
79 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
80
81 assert(call);
82
83 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
84 return 0;
85
86 if (sd_bus_error_is_set(p))
87 return synthetic_reply_method_error(call, p);
88
89 sd_bus_error_set_errno(&berror, error);
90
91 return synthetic_reply_method_error(call, &berror);
92 }
93
94 int synthetic_reply_method_errnof(sd_bus_message *call, int error, const char *format, ...) {
95 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
96 va_list ap;
97
98 assert(call);
99
100 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
101 return 0;
102
103 va_start(ap, format);
104 sd_bus_error_set_errnofv(&berror, error, format, ap);
105 va_end(ap);
106
107 return synthetic_reply_method_error(call, &berror);
108 }
109
110 int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
111 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
112 int r;
113
114 assert(call);
115
116 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
117 return 0;
118
119 r = sd_bus_message_new_method_return(call, &m);
120 if (r < 0)
121 return r;
122
123 if (!isempty(types)) {
124 va_list ap;
125
126 va_start(ap, types);
127 r = bus_message_append_ap(m, types, ap);
128 va_end(ap);
129 if (r < 0)
130 return r;
131 }
132
133 return synthetic_driver_send(call->bus, m);
134 }
135
136 int synthetic_reply_method_return_strv(sd_bus_message *call, char **l) {
137 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
138 int r;
139
140 assert(call);
141
142 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
143 return 0;
144
145 r = sd_bus_message_new_method_return(call, &m);
146 if (r < 0)
147 return synthetic_reply_method_errno(call, r, NULL);
148
149 r = sd_bus_message_append_strv(m, l);
150 if (r < 0)
151 return synthetic_reply_method_errno(call, r, NULL);
152
153 return synthetic_driver_send(call->bus, m);
154 }
155
156 int synthesize_name_acquired(Proxy *p, sd_bus *a, sd_bus *b, sd_bus_message *m) {
157 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
158 const char *name, *old_owner, *new_owner;
159 int r;
160
161 assert(p);
162 assert(a);
163 assert(b);
164 assert(m);
165
166 /* If we get NameOwnerChanged for our own name, we need to
167 * synthesize NameLost/NameAcquired, since socket clients need
168 * that, even though it is obsoleted on kdbus */
169
170 if (!a->is_kernel)
171 return 0;
172
173 if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
174 !streq_ptr(m->path, "/org/freedesktop/DBus") ||
175 !streq_ptr(m->sender, "org.freedesktop.DBus"))
176 return 0;
177
178 r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
179 if (r < 0)
180 return r;
181
182 r = sd_bus_message_rewind(m, true);
183 if (r < 0)
184 return r;
185
186 if (streq(old_owner, a->unique_name)) {
187
188 r = sd_bus_message_new_signal(
189 b,
190 &n,
191 "/org/freedesktop/DBus",
192 "org.freedesktop.DBus",
193 "NameLost");
194
195 } else if (streq(new_owner, a->unique_name)) {
196
197 r = sd_bus_message_new_signal(
198 b,
199 &n,
200 "/org/freedesktop/DBus",
201 "org.freedesktop.DBus",
202 "NameAcquired");
203 } else
204 return 0;
205
206 if (r < 0)
207 return r;
208
209 r = sd_bus_message_append(n, "s", name);
210 if (r < 0)
211 return r;
212
213 r = bus_message_append_sender(n, "org.freedesktop.DBus");
214 if (r < 0)
215 return r;
216
217 r = sd_bus_message_set_destination(n, a->unique_name);
218 if (r < 0)
219 return r;
220
221 r = bus_seal_synthetic_message(b, n);
222 if (r < 0)
223 return r;
224
225 return sd_bus_send(b, n, NULL);
226 }