1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "sd-daemon.h"
31 #include "bus-internal.h"
37 #define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
39 const char *arg_bus_path
= DEFAULT_BUS_PATH
;
41 static int help(void) {
43 printf("%s [OPTIONS...]\n\n"
44 "STDIO or socket-activatable proxy to a given DBus endpoint.\n\n"
45 " -h --help Show this help\n"
46 " --version Show package version\n"
47 " -p --bus-path=PATH Path to the kernel bus (default: %s)\n",
48 program_invocation_short_name
, DEFAULT_BUS_PATH
);
53 static int parse_argv(int argc
, char *argv
[]) {
59 static const struct option options
[] = {
60 { "help", no_argument
, NULL
, 'h' },
61 { "version", no_argument
, NULL
, ARG_VERSION
},
62 { "bus-path", required_argument
, NULL
, 'p' },
71 while ((c
= getopt_long(argc
, argv
, "hsup:", options
, NULL
)) >= 0) {
86 arg_bus_path
= optarg
;
90 log_error("Unknown option code %c", c
);
98 int main(int argc
, char *argv
[]) {
99 _cleanup_(sd_bus_unrefp
) sd_bus
*a
= NULL
, *b
= NULL
;
100 sd_id128_t server_id
;
102 int r
, in_fd
, out_fd
;
104 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG
);
105 log_parse_environment();
108 r
= parse_argv(argc
, argv
);
112 r
= sd_listen_fds(0);
114 in_fd
= STDIN_FILENO
;
115 out_fd
= STDOUT_FILENO
;
117 in_fd
= SD_LISTEN_FDS_START
;
118 out_fd
= SD_LISTEN_FDS_START
;
120 log_error("Illegal number of file descriptors passed.");
125 sd_is_socket(in_fd
, AF_UNIX
, 0, 0) > 0 &&
126 sd_is_socket(out_fd
, AF_UNIX
, 0, 0) > 0;
130 log_error_errno(r
, "Failed to allocate bus: %m");
134 r
= sd_bus_set_address(a
, arg_bus_path
);
136 log_error_errno(r
, "Failed to set address to connect to: %m");
140 r
= sd_bus_negotiate_fds(a
, is_unix
);
142 log_error_errno(r
, "Failed to set FD negotiation: %m");
148 log_error_errno(r
, "Failed to start bus client: %m");
152 r
= sd_bus_get_bus_id(a
, &server_id
);
154 log_error_errno(r
, "Failed to get server ID: %m");
160 log_error_errno(r
, "Failed to allocate bus: %m");
164 r
= sd_bus_set_fd(b
, in_fd
, out_fd
);
166 log_error_errno(r
, "Failed to set fds: %m");
170 r
= sd_bus_set_server(b
, 1, server_id
);
172 log_error_errno(r
, "Failed to set server mode: %m");
176 r
= sd_bus_negotiate_fds(b
, is_unix
);
178 log_error_errno(r
, "Failed to set FD negotiation: %m");
182 r
= sd_bus_set_anonymous(b
, true);
184 log_error_errno(r
, "Failed to set anonymous authentication: %m");
190 log_error_errno(r
, "Failed to start bus client: %m");
195 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
196 int events_a
, events_b
, fd
;
197 uint64_t timeout_a
, timeout_b
, t
;
198 struct timespec _ts
, *ts
;
200 r
= sd_bus_process(a
, &m
);
202 log_error_errno(r
, "Failed to process bus a: %m");
207 r
= sd_bus_send(b
, m
, NULL
);
209 log_error_errno(r
, "Failed to send message: %m");
217 r
= sd_bus_process(b
, &m
);
219 /* treat 'connection reset by peer' as clean exit condition */
220 if (r
== -ECONNRESET
)
227 r
= sd_bus_send(a
, m
, NULL
);
229 log_error_errno(r
, "Failed to send message: %m");
237 fd
= sd_bus_get_fd(a
);
240 log_error_errno(r
, "Failed to get fd: %m");
244 events_a
= sd_bus_get_events(a
);
247 log_error_errno(r
, "Failed to get events mask: %m");
251 r
= sd_bus_get_timeout(a
, &timeout_a
);
253 log_error_errno(r
, "Failed to get timeout: %m");
257 events_b
= sd_bus_get_events(b
);
260 log_error_errno(r
, "Failed to get events mask: %m");
264 r
= sd_bus_get_timeout(b
, &timeout_b
);
266 log_error_errno(r
, "Failed to get timeout: %m");
271 if (t
== (uint64_t) -1 || (timeout_b
!= (uint64_t) -1 && timeout_b
< timeout_a
))
274 if (t
== (uint64_t) -1)
279 nw
= now(CLOCK_MONOTONIC
);
285 ts
= timespec_store(&_ts
, t
);
289 struct pollfd p
[3] = {
290 {.fd
= fd
, .events
= events_a
, },
291 {.fd
= STDIN_FILENO
, .events
= events_b
& POLLIN
, },
292 {.fd
= STDOUT_FILENO
, .events
= events_b
& POLLOUT
, }};
294 r
= ppoll(p
, ELEMENTSOF(p
), ts
, NULL
);
297 log_error_errno(errno
, "ppoll() failed: %m");
303 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;