1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
10 systemd is free software; you can redistribute it and/or modify it
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
20 You should have received a copy of the GNU Lesser General Public License
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include <sys/socket.h>
26 #include <sys/types.h>
37 #include "socket-util.h"
38 #include "sd-daemon.h"
40 #include "bus-internal.h"
41 #include "bus-message.h"
46 #include "capability.h"
47 #include "bus-control.h"
48 #include "smack-util.h"
50 #include "bus-xml-policy.h"
53 #include "synthesize.h"
55 static char *arg_address = NULL;
56 static char *arg_command_line_buffer = NULL;
58 static int help(void) {
60 printf("%s [OPTIONS...]\n\n"
61 "Connect STDIO to a given bus address.\n\n"
62 " -h --help Show this help\n"
63 " --version Show package version\n"
64 " --machine=MACHINE Connect to specified machine\n"
65 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
66 " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
67 program_invocation_short_name);
72 static int parse_argv(int argc, char *argv[]) {
80 static const struct option options[] = {
81 { "help", no_argument, NULL, 'h' },
82 { "version", no_argument, NULL, ARG_VERSION },
83 { "address", required_argument, NULL, ARG_ADDRESS },
84 { "machine", required_argument, NULL, ARG_MACHINE },
93 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
102 puts(PACKAGE_STRING);
103 puts(SYSTEMD_FEATURES);
119 _cleanup_free_ char *e = NULL;
122 e = bus_address_escape(optarg);
127 a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
129 a = strjoin("x-machine-unix:machine=", e, NULL);
144 assert_not_reached("Unhandled option");
147 /* If the first command line argument is only "x" characters
148 * we'll write who we are talking to into it, so that "ps" is
150 arg_command_line_buffer = argv[optind];
151 if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
152 log_error("Too many arguments");
157 arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
165 static int rename_service(sd_bus *a, sd_bus *b) {
166 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
167 _cleanup_free_ char *p = NULL, *name = NULL;
177 r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds);
181 r = sd_bus_creds_get_euid(creds, &uid);
185 r = sd_bus_creds_get_pid(creds, &pid);
189 r = sd_bus_creds_get_cmdline(creds, &cmdline);
193 r = sd_bus_creds_get_comm(creds, &comm);
197 name = uid_to_name(uid);
201 p = strv_join(cmdline, " ");
205 /* The status string gets the full command line ... */
207 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
211 /* ... and the argv line only the short comm */
212 if (arg_command_line_buffer) {
215 m = strlen(arg_command_line_buffer);
216 w = snprintf(arg_command_line_buffer, m,
217 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
222 memzero(arg_command_line_buffer + w, m - w);
225 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
233 int main(int argc, char *argv[]) {
234 _cleanup_(proxy_freep) Proxy *p = NULL;
237 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
238 log_parse_environment();
241 r = parse_argv(argc, argv);
245 r = proxy_new(&p, STDIN_FILENO, STDOUT_FILENO, arg_address);
249 r = rename_service(p->dest_bus, p->local_bus);
251 log_debug_errno(r, "Failed to rename process: %m");
258 "STATUS=Shutting down.");
262 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;