2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "sd-daemon.h"
30 #include "bus-internal.h"
36 #define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
38 const char *arg_bus_path
= DEFAULT_BUS_PATH
;
40 static int help(void) {
42 printf("%s [OPTIONS...]\n\n"
43 "STDIO or socket-activatable proxy to a given DBus endpoint.\n\n"
44 " -h --help Show this help\n"
45 " --version Show package version\n"
46 " --bus-path=PATH Path to the kernel bus (default: %s)\n",
47 program_invocation_short_name
, DEFAULT_BUS_PATH
);
52 static int parse_argv(int argc
, char *argv
[]) {
58 static const struct option options
[] = {
59 { "help", no_argument
, NULL
, 'h' },
60 { "bus-path", required_argument
, NULL
, 'p' },
69 while ((c
= getopt_long(argc
, argv
, "hsup:", options
, NULL
)) >= 0) {
84 arg_bus_path
= optarg
;
88 log_error("Unknown option code %c", c
);
96 int main(int argc
, char *argv
[]) {
97 _cleanup_(sd_bus_unrefp
) sd_bus
*a
= NULL
, *b
= NULL
;
100 int r
, in_fd
, out_fd
;
102 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG
);
103 log_parse_environment();
106 r
= parse_argv(argc
, argv
);
110 r
= sd_listen_fds(0);
112 in_fd
= STDIN_FILENO
;
113 out_fd
= STDOUT_FILENO
;
115 in_fd
= SD_LISTEN_FDS_START
;
116 out_fd
= SD_LISTEN_FDS_START
;
118 log_error("Illegal number of file descriptors passed\n");
123 sd_is_socket(in_fd
, AF_UNIX
, 0, 0) > 0 &&
124 sd_is_socket(out_fd
, AF_UNIX
, 0, 0) > 0;
128 log_error_errno(r
, "Failed to allocate bus: %m");
132 r
= sd_bus_set_address(a
, arg_bus_path
);
134 log_error_errno(r
, "Failed to set address to connect to: %m");
138 r
= sd_bus_negotiate_fds(a
, is_unix
);
140 log_error_errno(r
, "Failed to set FD negotiation: %m");
146 log_error_errno(r
, "Failed to start bus client: %m");
150 r
= sd_bus_get_bus_id(a
, &server_id
);
152 log_error_errno(r
, "Failed to get server ID: %m");
158 log_error_errno(r
, "Failed to allocate bus: %m");
162 r
= sd_bus_set_fd(b
, in_fd
, out_fd
);
164 log_error_errno(r
, "Failed to set fds: %m");
168 r
= sd_bus_set_server(b
, 1, server_id
);
170 log_error_errno(r
, "Failed to set server mode: %m");
174 r
= sd_bus_negotiate_fds(b
, is_unix
);
176 log_error_errno(r
, "Failed to set FD negotiation: %m");
180 r
= sd_bus_set_anonymous(b
, true);
182 log_error_errno(r
, "Failed to set anonymous authentication: %m");
188 log_error_errno(r
, "Failed to start bus client: %m");
193 _cleanup_(sd_bus_message_unrefp
)sd_bus_message
*m
= NULL
;
194 int events_a
, events_b
, fd
;
195 uint64_t timeout_a
, timeout_b
, t
;
196 struct timespec _ts
, *ts
;
198 r
= sd_bus_process(a
, &m
);
200 log_error_errno(r
, "Failed to process bus a: %m");
205 r
= sd_bus_send(b
, m
, NULL
);
207 log_error_errno(r
, "Failed to send message: %m");
215 r
= sd_bus_process(b
, &m
);
217 /* treat 'connection reset by peer' as clean exit condition */
218 if (r
== -ECONNRESET
)
225 r
= sd_bus_send(a
, m
, NULL
);
227 log_error_errno(r
, "Failed to send message: %m");
235 fd
= sd_bus_get_fd(a
);
237 log_error_errno(r
, "Failed to get fd: %m");
241 events_a
= sd_bus_get_events(a
);
243 log_error_errno(r
, "Failed to get events mask: %m");
247 r
= sd_bus_get_timeout(a
, &timeout_a
);
249 log_error_errno(r
, "Failed to get timeout: %m");
253 events_b
= sd_bus_get_events(b
);
255 log_error_errno(r
, "Failed to get events mask: %m");
259 r
= sd_bus_get_timeout(b
, &timeout_b
);
261 log_error_errno(r
, "Failed to get timeout: %m");
266 if (t
== (uint64_t) -1 || (timeout_b
!= (uint64_t) -1 && timeout_b
< timeout_a
))
269 if (t
== (uint64_t) -1)
274 nw
= now(CLOCK_MONOTONIC
);
280 ts
= timespec_store(&_ts
, t
);
284 struct pollfd p
[3] = {
285 {.fd
= fd
, .events
= events_a
, },
286 {.fd
= STDIN_FILENO
, .events
= events_b
& POLLIN
, },
287 {.fd
= STDOUT_FILENO
, .events
= events_b
& POLLOUT
, }};
289 r
= ppoll(p
, ELEMENTSOF(p
), ts
, NULL
);
292 log_error("ppoll() failed: %m");
298 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;