1 /* SPDX-License-Identifier: LGPL-2.1+ */
11 #include "sd-daemon.h"
13 #include "alloc-util.h"
15 #include "bus-internal.h"
18 #include "main-func.h"
21 #define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
23 static const char *arg_bus_path
= DEFAULT_BUS_PATH
;
24 static BusTransport arg_transport
= BUS_TRANSPORT_LOCAL
;
26 static int help(void) {
28 printf("%s [OPTIONS...]\n\n"
29 "STDIO or socket-activatable proxy to a given DBus endpoint.\n\n"
30 " -h --help Show this help\n"
31 " --version Show package version\n"
32 " -p --bus-path=PATH Path to the kernel bus (default: %s)\n"
33 " -M --machine=MACHINE Name of machine to connect to\n",
34 program_invocation_short_name
, DEFAULT_BUS_PATH
);
39 static int parse_argv(int argc
, char *argv
[]) {
46 static const struct option options
[] = {
47 { "help", no_argument
, NULL
, 'h' },
48 { "version", no_argument
, NULL
, ARG_VERSION
},
49 { "bus-path", required_argument
, NULL
, 'p' },
50 { "machine", required_argument
, NULL
, 'M' },
59 while ((c
= getopt_long(argc
, argv
, "hsup:", options
, NULL
)) >= 0) {
74 arg_bus_path
= optarg
;
79 arg_bus_path
= optarg
;
81 arg_transport
= BUS_TRANSPORT_MACHINE
;
85 log_error("Unknown option code %c", c
);
93 static int run(int argc
, char *argv
[]) {
94 _cleanup_(sd_bus_unrefp
) sd_bus
*a
= NULL
, *b
= NULL
;
99 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG
);
100 log_parse_environment();
103 r
= parse_argv(argc
, argv
);
107 r
= sd_listen_fds(0);
109 in_fd
= STDIN_FILENO
;
110 out_fd
= STDOUT_FILENO
;
112 in_fd
= SD_LISTEN_FDS_START
;
113 out_fd
= SD_LISTEN_FDS_START
;
115 log_error("Illegal number of file descriptors passed.");
120 sd_is_socket(in_fd
, AF_UNIX
, 0, 0) > 0 &&
121 sd_is_socket(out_fd
, AF_UNIX
, 0, 0) > 0;
125 return log_error_errno(r
, "Failed to allocate bus: %m");
127 if (arg_transport
== BUS_TRANSPORT_MACHINE
)
128 r
= bus_set_address_system_machine(a
, arg_bus_path
);
130 r
= sd_bus_set_address(a
, arg_bus_path
);
132 return log_error_errno(r
, "Failed to set address to connect to: %m");
134 r
= sd_bus_negotiate_fds(a
, is_unix
);
136 return log_error_errno(r
, "Failed to set FD negotiation: %m");
140 return log_error_errno(r
, "Failed to start bus client: %m");
142 r
= sd_bus_get_bus_id(a
, &server_id
);
144 return log_error_errno(r
, "Failed to get server ID: %m");
148 return log_error_errno(r
, "Failed to allocate bus: %m");
150 r
= sd_bus_set_fd(b
, in_fd
, out_fd
);
152 return log_error_errno(r
, "Failed to set fds: %m");
154 r
= sd_bus_set_server(b
, 1, server_id
);
156 return log_error_errno(r
, "Failed to set server mode: %m");
158 r
= sd_bus_negotiate_fds(b
, is_unix
);
160 return log_error_errno(r
, "Failed to set FD negotiation: %m");
162 r
= sd_bus_set_anonymous(b
, true);
164 return log_error_errno(r
, "Failed to set anonymous authentication: %m");
168 return log_error_errno(r
, "Failed to start bus client: %m");
171 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
172 int events_a
, events_b
, fd
;
173 uint64_t timeout_a
, timeout_b
, t
;
174 struct timespec _ts
, *ts
;
176 r
= sd_bus_process(a
, &m
);
178 return log_error_errno(r
, "Failed to process bus a: %m");
181 r
= sd_bus_send(b
, m
, NULL
);
183 return log_error_errno(r
, "Failed to send message: %m");
189 r
= sd_bus_process(b
, &m
);
191 /* treat 'connection reset by peer' as clean exit condition */
192 return r
== -ECONNRESET
? 0 : r
;
195 r
= sd_bus_send(a
, m
, NULL
);
197 return log_error_errno(r
, "Failed to send message: %m");
203 fd
= sd_bus_get_fd(a
);
205 return log_error_errno(fd
, "Failed to get fd: %m");
207 events_a
= sd_bus_get_events(a
);
209 return log_error_errno(events_a
, "Failed to get events mask: %m");
211 r
= sd_bus_get_timeout(a
, &timeout_a
);
213 return log_error_errno(r
, "Failed to get timeout: %m");
215 events_b
= sd_bus_get_events(b
);
217 return log_error_errno(events_b
, "Failed to get events mask: %m");
219 r
= sd_bus_get_timeout(b
, &timeout_b
);
221 return log_error_errno(r
, "Failed to get timeout: %m");
224 if (t
== (uint64_t) -1 || (timeout_b
!= (uint64_t) -1 && timeout_b
< timeout_a
))
227 if (t
== (uint64_t) -1)
232 nw
= now(CLOCK_MONOTONIC
);
238 ts
= timespec_store(&_ts
, t
);
242 struct pollfd p
[3] = {
243 {.fd
= fd
, .events
= events_a
, },
244 {.fd
= STDIN_FILENO
, .events
= events_b
& POLLIN
, },
245 {.fd
= STDOUT_FILENO
, .events
= events_b
& POLLOUT
, }};
247 r
= ppoll(p
, ELEMENTSOF(p
), ts
, NULL
);
250 return log_error_errno(errno
, "ppoll() failed: %m");
256 DEFINE_MAIN_FUNCTION(run
);