LCOV - code coverage report
Current view: top level - stdio-bridge - stdio-bridge.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 21 132 15.9 %
Date: 2019-08-22 15:41:25 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <getopt.h>
       5             : #include <poll.h>
       6             : #include <stddef.h>
       7             : #include <string.h>
       8             : #include <unistd.h>
       9             : 
      10             : #include "sd-bus.h"
      11             : #include "sd-daemon.h"
      12             : 
      13             : #include "alloc-util.h"
      14             : #include "build.h"
      15             : #include "bus-internal.h"
      16             : #include "bus-util.h"
      17             : #include "errno-util.h"
      18             : #include "log.h"
      19             : #include "main-func.h"
      20             : #include "util.h"
      21             : 
      22             : #define DEFAULT_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
      23             : 
      24             : static const char *arg_bus_path = DEFAULT_BUS_PATH;
      25             : static BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
      26             : 
      27           3 : static int help(void) {
      28             : 
      29           3 :         printf("%s [OPTIONS...]\n\n"
      30             :                "STDIO or socket-activatable proxy to a given DBus endpoint.\n\n"
      31             :                "  -h --help              Show this help\n"
      32             :                "     --version           Show package version\n"
      33             :                "  -p --bus-path=PATH     Path to the kernel bus (default: %s)\n"
      34             :                "  -M --machine=MACHINE   Name of machine to connect to\n",
      35             :                program_invocation_short_name, DEFAULT_BUS_PATH);
      36             : 
      37           3 :         return 0;
      38             : }
      39             : 
      40           4 : static int parse_argv(int argc, char *argv[]) {
      41             : 
      42             :         enum {
      43             :                 ARG_VERSION = 0x100,
      44             :                 ARG_MACHINE,
      45             :         };
      46             : 
      47             :         static const struct option options[] = {
      48             :                 { "help",            no_argument,       NULL, 'h'         },
      49             :                 { "version",         no_argument,       NULL, ARG_VERSION },
      50             :                 { "bus-path",        required_argument, NULL, 'p'         },
      51             :                 { "machine",         required_argument, NULL, 'M'         },
      52             :                 {},
      53             :         };
      54             : 
      55             :         int c;
      56             : 
      57           4 :         assert(argc >= 0);
      58           4 :         assert(argv);
      59             : 
      60           4 :         while ((c = getopt_long(argc, argv, "hp:M:", options, NULL)) >= 0) {
      61             : 
      62           4 :                 switch (c) {
      63             : 
      64           3 :                 case 'h':
      65           3 :                         return help();
      66             : 
      67           0 :                 case ARG_VERSION:
      68           0 :                         return version();
      69             : 
      70           0 :                 case 'p':
      71           0 :                         arg_bus_path = optarg;
      72           0 :                         break;
      73             : 
      74           0 :                 case 'M':
      75           0 :                         arg_bus_path = optarg;
      76           0 :                         arg_transport = BUS_TRANSPORT_MACHINE;
      77           0 :                         break;
      78             : 
      79           1 :                 case '?':
      80           1 :                         return -EINVAL;
      81             : 
      82           0 :                 default:
      83           0 :                         return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
      84             :                                                "Unknown option code %c", c);
      85             :                 }
      86             :         }
      87             : 
      88           0 :         return 1;
      89             : }
      90             : 
      91           4 : static int run(int argc, char *argv[]) {
      92           4 :         _cleanup_(sd_bus_flush_close_unrefp) sd_bus *a = NULL, *b = NULL;
      93             :         sd_id128_t server_id;
      94             :         bool is_unix;
      95             :         int r, in_fd, out_fd;
      96             : 
      97           4 :         log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
      98           4 :         log_parse_environment();
      99           4 :         log_open();
     100             : 
     101           4 :         r = parse_argv(argc, argv);
     102           4 :         if (r <= 0)
     103           4 :                 return r;
     104             : 
     105           0 :         r = sd_listen_fds(0);
     106           0 :         if (r == 0) {
     107           0 :                 in_fd = STDIN_FILENO;
     108           0 :                 out_fd = STDOUT_FILENO;
     109           0 :         } else if (r == 1) {
     110           0 :                 in_fd = SD_LISTEN_FDS_START;
     111           0 :                 out_fd = SD_LISTEN_FDS_START;
     112             :         } else
     113           0 :                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Illegal number of file descriptors passed.");
     114             : 
     115           0 :         is_unix =
     116           0 :                 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
     117           0 :                 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
     118             : 
     119           0 :         r = sd_bus_new(&a);
     120           0 :         if (r < 0)
     121           0 :                 return log_error_errno(r, "Failed to allocate bus: %m");
     122             : 
     123           0 :         if (arg_transport == BUS_TRANSPORT_MACHINE)
     124           0 :                 r = bus_set_address_system_machine(a, arg_bus_path);
     125             :         else
     126           0 :                 r = sd_bus_set_address(a, arg_bus_path);
     127           0 :         if (r < 0)
     128           0 :                 return log_error_errno(r, "Failed to set address to connect to: %m");
     129             : 
     130           0 :         r = sd_bus_negotiate_fds(a, is_unix);
     131           0 :         if (r < 0)
     132           0 :                 return log_error_errno(r, "Failed to set FD negotiation: %m");
     133             : 
     134           0 :         r = sd_bus_start(a);
     135           0 :         if (r < 0)
     136           0 :                 return log_error_errno(r, "Failed to start bus client: %m");
     137             : 
     138           0 :         r = sd_bus_get_bus_id(a, &server_id);
     139           0 :         if (r < 0)
     140           0 :                 return log_error_errno(r, "Failed to get server ID: %m");
     141             : 
     142           0 :         r = sd_bus_new(&b);
     143           0 :         if (r < 0)
     144           0 :                 return log_error_errno(r, "Failed to allocate bus: %m");
     145             : 
     146           0 :         r = sd_bus_set_fd(b, in_fd, out_fd);
     147           0 :         if (r < 0)
     148           0 :                 return log_error_errno(r, "Failed to set fds: %m");
     149             : 
     150           0 :         r = sd_bus_set_server(b, 1, server_id);
     151           0 :         if (r < 0)
     152           0 :                 return log_error_errno(r, "Failed to set server mode: %m");
     153             : 
     154           0 :         r = sd_bus_negotiate_fds(b, is_unix);
     155           0 :         if (r < 0)
     156           0 :                 return log_error_errno(r, "Failed to set FD negotiation: %m");
     157             : 
     158           0 :         r = sd_bus_set_anonymous(b, true);
     159           0 :         if (r < 0)
     160           0 :                 return log_error_errno(r, "Failed to set anonymous authentication: %m");
     161             : 
     162           0 :         r = sd_bus_start(b);
     163           0 :         if (r < 0)
     164           0 :                 return log_error_errno(r, "Failed to start bus client: %m");
     165             : 
     166           0 :         for (;;) {
     167           0 :                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
     168             :                 int events_a, events_b, fd;
     169             :                 uint64_t timeout_a, timeout_b, t;
     170             :                 struct timespec _ts, *ts;
     171             : 
     172           0 :                 r = sd_bus_process(a, &m);
     173           0 :                 if (r < 0)
     174           0 :                         return log_error_errno(r, "Failed to process bus a: %m");
     175             : 
     176           0 :                 if (m) {
     177           0 :                         r = sd_bus_send(b, m, NULL);
     178           0 :                         if (r < 0)
     179           0 :                                 return log_error_errno(r, "Failed to send message: %m");
     180             :                 }
     181             : 
     182           0 :                 if (r > 0)
     183           0 :                         continue;
     184             : 
     185           0 :                 r = sd_bus_process(b, &m);
     186           0 :                 if (r < 0) {
     187             :                         /* treat 'connection reset by peer' as clean exit condition */
     188           0 :                         if (ERRNO_IS_DISCONNECT(r))
     189           0 :                                 return 0;
     190             : 
     191           0 :                         return log_error_errno(r, "Failed to process bus: %m");
     192             :                 }
     193             : 
     194           0 :                 if (m) {
     195           0 :                         r = sd_bus_send(a, m, NULL);
     196           0 :                         if (r < 0)
     197           0 :                                 return log_error_errno(r, "Failed to send message: %m");
     198             :                 }
     199             : 
     200           0 :                 if (r > 0)
     201           0 :                         continue;
     202             : 
     203           0 :                 fd = sd_bus_get_fd(a);
     204           0 :                 if (fd < 0)
     205           0 :                         return log_error_errno(fd, "Failed to get fd: %m");
     206             : 
     207           0 :                 events_a = sd_bus_get_events(a);
     208           0 :                 if (events_a < 0)
     209           0 :                         return log_error_errno(events_a, "Failed to get events mask: %m");
     210             : 
     211           0 :                 r = sd_bus_get_timeout(a, &timeout_a);
     212           0 :                 if (r < 0)
     213           0 :                         return log_error_errno(r, "Failed to get timeout: %m");
     214             : 
     215           0 :                 events_b = sd_bus_get_events(b);
     216           0 :                 if (events_b < 0)
     217           0 :                         return log_error_errno(events_b, "Failed to get events mask: %m");
     218             : 
     219           0 :                 r = sd_bus_get_timeout(b, &timeout_b);
     220           0 :                 if (r < 0)
     221           0 :                         return log_error_errno(r, "Failed to get timeout: %m");
     222             : 
     223           0 :                 t = timeout_a;
     224           0 :                 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
     225           0 :                         t = timeout_b;
     226             : 
     227           0 :                 if (t == (uint64_t) -1)
     228           0 :                         ts = NULL;
     229             :                 else {
     230             :                         usec_t nw;
     231             : 
     232           0 :                         nw = now(CLOCK_MONOTONIC);
     233           0 :                         if (t > nw)
     234           0 :                                 t -= nw;
     235             :                         else
     236           0 :                                 t = 0;
     237             : 
     238           0 :                         ts = timespec_store(&_ts, t);
     239             :                 }
     240             : 
     241             :                 {
     242           0 :                         struct pollfd p[3] = {
     243             :                                 {.fd = fd,            .events = events_a           },
     244           0 :                                 {.fd = STDIN_FILENO,  .events = events_b & POLLIN  },
     245           0 :                                 {.fd = STDOUT_FILENO, .events = events_b & POLLOUT },
     246             :                         };
     247             : 
     248           0 :                         r = ppoll(p, ELEMENTSOF(p), ts, NULL);
     249             :                 }
     250           0 :                 if (r < 0)
     251           0 :                         return log_error_errno(errno, "ppoll() failed: %m");
     252             :         }
     253             : 
     254             :         return 0;
     255             : }
     256             : 
     257           4 : DEFINE_MAIN_FUNCTION(run);

Generated by: LCOV version 1.14