LCOV - code coverage report
Current view: top level - stdio-bridge - stdio-bridge.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 21 132 15.9 %
Date: 2019-08-23 13:36:53 Functions: 4 4 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 6 135 4.4 %

           Branch data     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                 :         12 : static int help(void) {
      28                 :            : 
      29                 :         12 :         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                 :         12 :         return 0;
      38                 :            : }
      39                 :            : 
      40                 :         16 : 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         [ -  + ]:         16 :         assert(argc >= 0);
      58         [ -  + ]:         16 :         assert(argv);
      59                 :            : 
      60         [ +  - ]:         16 :         while ((c = getopt_long(argc, argv, "hp:M:", options, NULL)) >= 0) {
      61                 :            : 
      62   [ +  -  -  -  :         16 :                 switch (c) {
                   +  - ]
      63                 :            : 
      64                 :         12 :                 case 'h':
      65                 :         12 :                         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                 :          4 :                 case '?':
      80                 :          4 :                         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                 :         16 : static int run(int argc, char *argv[]) {
      92                 :         16 :         _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                 :         16 :         log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
      98                 :         16 :         log_parse_environment();
      99                 :         16 :         log_open();
     100                 :            : 
     101                 :         16 :         r = parse_argv(argc, argv);
     102         [ +  - ]:         16 :         if (r <= 0)
     103                 :         16 :                 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                 :         16 : DEFINE_MAIN_FUNCTION(run);

Generated by: LCOV version 1.14