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;
57 static char **arg_configuration = NULL;
59 static int help(void) {
61 printf("%s [OPTIONS...]\n\n"
62 "Connect STDIO to a given bus address.\n\n"
63 " -h --help Show this help\n"
64 " --version Show package version\n"
65 " --configuration=PATH Configuration file or directory\n"
66 " --machine=MACHINE Connect to specified machine\n"
67 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
68 " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
69 program_invocation_short_name);
74 static int parse_argv(int argc, char *argv[]) {
83 static const struct option options[] = {
84 { "help", no_argument, NULL, 'h' },
85 { "version", no_argument, NULL, ARG_VERSION },
86 { "address", required_argument, NULL, ARG_ADDRESS },
87 { "configuration", required_argument, NULL, ARG_CONFIGURATION },
88 { "machine", required_argument, NULL, ARG_MACHINE },
97 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
106 puts(PACKAGE_STRING);
107 puts(SYSTEMD_FEATURES);
122 case ARG_CONFIGURATION:
123 r = strv_extend(&arg_configuration, optarg);
129 _cleanup_free_ char *e = NULL;
132 e = bus_address_escape(optarg);
137 a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
139 a = strjoin("x-machine-unix:machine=", e, NULL);
154 assert_not_reached("Unhandled option");
157 /* If the first command line argument is only "x" characters
158 * we'll write who we are talking to into it, so that "ps" is
160 arg_command_line_buffer = argv[optind];
161 if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
162 log_error("Too many arguments");
167 arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
175 static int rename_service(sd_bus *a, sd_bus *b) {
176 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
177 _cleanup_free_ char *p = NULL, *name = NULL;
187 r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds);
191 r = sd_bus_creds_get_uid(creds, &uid);
195 r = sd_bus_creds_get_pid(creds, &pid);
199 r = sd_bus_creds_get_cmdline(creds, &cmdline);
203 r = sd_bus_creds_get_comm(creds, &comm);
207 name = uid_to_name(uid);
211 p = strv_join(cmdline, " ");
215 /* The status string gets the full command line ... */
217 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
221 /* ... and the argv line only the short comm */
222 if (arg_command_line_buffer) {
225 m = strlen(arg_command_line_buffer);
226 w = snprintf(arg_command_line_buffer, m,
227 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
232 memzero(arg_command_line_buffer + w, m - w);
235 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
243 int main(int argc, char *argv[]) {
244 _cleanup_(proxy_freep) Proxy *p = NULL;
247 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
248 log_parse_environment();
251 r = parse_argv(argc, argv);
255 r = proxy_new(&p, STDIN_FILENO, STDOUT_FILENO, arg_address);
259 r = proxy_load_policy(p, arg_configuration);
263 r = proxy_hello_policy(p, getuid());
267 r = rename_service(p->dest_bus, p->local_bus);
269 log_debug_errno(r, "Failed to rename process: %m");
276 "STATUS=Shutting down.");
278 strv_free(arg_configuration);
281 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;