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 " --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 { "bus-path", required_argument
, NULL
, 'p' },
70 while ((c
= getopt_long(argc
, argv
, "hsup:", options
, NULL
)) >= 0) {
85 arg_bus_path
= optarg
;
89 log_error("Unknown option code %c", c
);
97 int main(int argc
, char *argv
[]) {
98 _cleanup_(sd_bus_unrefp
) sd_bus
*a
= NULL
, *b
= NULL
;
101 int r
, in_fd
, out_fd
;
103 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG
);
104 log_parse_environment();
107 r
= parse_argv(argc
, argv
);
111 r
= sd_listen_fds(0);
113 in_fd
= STDIN_FILENO
;
114 out_fd
= STDOUT_FILENO
;
116 in_fd
= SD_LISTEN_FDS_START
;
117 out_fd
= SD_LISTEN_FDS_START
;
119 log_error("Illegal number of file descriptors passed.");
124 sd_is_socket(in_fd
, AF_UNIX
, 0, 0) > 0 &&
125 sd_is_socket(out_fd
, AF_UNIX
, 0, 0) > 0;
129 log_error_errno(r
, "Failed to allocate bus: %m");
133 r
= sd_bus_set_address(a
, arg_bus_path
);
135 log_error_errno(r
, "Failed to set address to connect to: %m");
139 r
= sd_bus_negotiate_fds(a
, is_unix
);
141 log_error_errno(r
, "Failed to set FD negotiation: %m");
147 log_error_errno(r
, "Failed to start bus client: %m");
151 r
= sd_bus_get_bus_id(a
, &server_id
);
153 log_error_errno(r
, "Failed to get server ID: %m");
159 log_error_errno(r
, "Failed to allocate bus: %m");
163 r
= sd_bus_set_fd(b
, in_fd
, out_fd
);
165 log_error_errno(r
, "Failed to set fds: %m");
169 r
= sd_bus_set_server(b
, 1, server_id
);
171 log_error_errno(r
, "Failed to set server mode: %m");
175 r
= sd_bus_negotiate_fds(b
, is_unix
);
177 log_error_errno(r
, "Failed to set FD negotiation: %m");
181 r
= sd_bus_set_anonymous(b
, true);
183 log_error_errno(r
, "Failed to set anonymous authentication: %m");
189 log_error_errno(r
, "Failed to start bus client: %m");
194 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
195 int events_a
, events_b
, fd
;
196 uint64_t timeout_a
, timeout_b
, t
;
197 struct timespec _ts
, *ts
;
199 r
= sd_bus_process(a
, &m
);
201 log_error_errno(r
, "Failed to process bus a: %m");
206 r
= sd_bus_send(b
, m
, NULL
);
208 log_error_errno(r
, "Failed to send message: %m");
216 r
= sd_bus_process(b
, &m
);
218 /* treat 'connection reset by peer' as clean exit condition */
219 if (r
== -ECONNRESET
)
226 r
= sd_bus_send(a
, m
, NULL
);
228 log_error_errno(r
, "Failed to send message: %m");
236 fd
= sd_bus_get_fd(a
);
239 log_error_errno(r
, "Failed to get fd: %m");
243 events_a
= sd_bus_get_events(a
);
246 log_error_errno(r
, "Failed to get events mask: %m");
250 r
= sd_bus_get_timeout(a
, &timeout_a
);
252 log_error_errno(r
, "Failed to get timeout: %m");
256 events_b
= sd_bus_get_events(b
);
259 log_error_errno(r
, "Failed to get events mask: %m");
263 r
= sd_bus_get_timeout(b
, &timeout_b
);
265 log_error_errno(r
, "Failed to get timeout: %m");
270 if (t
== (uint64_t) -1 || (timeout_b
!= (uint64_t) -1 && timeout_b
< timeout_a
))
273 if (t
== (uint64_t) -1)
278 nw
= now(CLOCK_MONOTONIC
);
284 ts
= timespec_store(&_ts
, t
);
288 struct pollfd p
[3] = {
289 {.fd
= fd
, .events
= events_a
, },
290 {.fd
= STDIN_FILENO
, .events
= events_b
& POLLIN
, },
291 {.fd
= STDOUT_FILENO
, .events
= events_b
& POLLOUT
, }};
293 r
= ppoll(p
, ELEMENTSOF(p
), ts
, NULL
);
296 log_error_errno(errno
, "ppoll() failed: %m");
302 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;