]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/bus-proxyd/stdio-bridge.c
Merge pull request #2495 from heftig/master
[thirdparty/systemd.git] / src / bus-proxyd / stdio-bridge.c
CommitLineData
f299e3e4
DH
1/***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5 Copyright 2013 Daniel Mack
6 Copyright 2014 Kay Sievers
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
f299e3e4 22#include <errno.h>
f299e3e4 23#include <getopt.h>
3f6fd1ba
LP
24#include <stddef.h>
25#include <string.h>
26#include <unistd.h>
f299e3e4 27
f299e3e4 28#include "sd-bus.h"
cf0fbc49 29#include "sd-daemon.h"
3f6fd1ba 30
b5efdb8a 31#include "alloc-util.h"
f299e3e4 32#include "bus-internal.h"
f299e3e4 33#include "bus-util.h"
f299e3e4 34#include "def.h"
6482f626 35#include "formats-util.h"
3f6fd1ba
LP
36#include "log.h"
37#include "proxy.h"
38#include "strv.h"
b1d4f8e1 39#include "user-util.h"
3f6fd1ba 40#include "util.h"
f299e3e4
DH
41
42static char *arg_address = NULL;
43static char *arg_command_line_buffer = NULL;
f299e3e4
DH
44
45static int help(void) {
46
47 printf("%s [OPTIONS...]\n\n"
48 "Connect STDIO to a given bus address.\n\n"
49 " -h --help Show this help\n"
50 " --version Show package version\n"
f299e3e4
DH
51 " --machine=MACHINE Connect to specified machine\n"
52 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
057171ef
DH
53 " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
54 program_invocation_short_name);
f299e3e4
DH
55
56 return 0;
57}
58
59static int parse_argv(int argc, char *argv[]) {
60
61 enum {
62 ARG_VERSION = 0x100,
63 ARG_ADDRESS,
f299e3e4
DH
64 ARG_MACHINE,
65 };
66
67 static const struct option options[] = {
68 { "help", no_argument, NULL, 'h' },
69 { "version", no_argument, NULL, ARG_VERSION },
70 { "address", required_argument, NULL, ARG_ADDRESS },
f299e3e4
DH
71 { "machine", required_argument, NULL, ARG_MACHINE },
72 {},
73 };
74
c4bc1a84 75 int c;
f299e3e4
DH
76
77 assert(argc >= 0);
78 assert(argv);
79
80 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
81
82 switch (c) {
83
84 case 'h':
85 help();
86 return 0;
87
88 case ARG_VERSION:
3f6fd1ba 89 return version();
f299e3e4
DH
90
91 case ARG_ADDRESS: {
92 char *a;
93
94 a = strdup(optarg);
95 if (!a)
96 return log_oom();
97
98 free(arg_address);
99 arg_address = a;
100 break;
101 }
102
f299e3e4
DH
103 case ARG_MACHINE: {
104 _cleanup_free_ char *e = NULL;
105 char *a;
106
107 e = bus_address_escape(optarg);
108 if (!e)
109 return log_oom();
110
f299e3e4 111 a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
f299e3e4
DH
112 if (!a)
113 return log_oom();
114
115 free(arg_address);
116 arg_address = a;
117
118 break;
119 }
120
121 case '?':
122 return -EINVAL;
123
124 default:
125 assert_not_reached("Unhandled option");
126 }
127
128 /* If the first command line argument is only "x" characters
129 * we'll write who we are talking to into it, so that "ps" is
130 * explanatory */
131 arg_command_line_buffer = argv[optind];
132 if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
133 log_error("Too many arguments");
134 return -EINVAL;
135 }
136
137 if (!arg_address) {
057171ef 138 arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
f299e3e4
DH
139 if (!arg_address)
140 return log_oom();
141 }
142
143 return 1;
144}
145
146static int rename_service(sd_bus *a, sd_bus *b) {
4afd3348 147 _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
f299e3e4
DH
148 _cleanup_free_ char *p = NULL, *name = NULL;
149 const char *comm;
150 char **cmdline;
151 uid_t uid;
152 pid_t pid;
153 int r;
154
155 assert(a);
156 assert(b);
157
05bae4a6 158 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);
f299e3e4
DH
159 if (r < 0)
160 return r;
161
05bae4a6 162 r = sd_bus_creds_get_euid(creds, &uid);
f299e3e4
DH
163 if (r < 0)
164 return r;
165
166 r = sd_bus_creds_get_pid(creds, &pid);
167 if (r < 0)
168 return r;
169
170 r = sd_bus_creds_get_cmdline(creds, &cmdline);
171 if (r < 0)
172 return r;
173
174 r = sd_bus_creds_get_comm(creds, &comm);
175 if (r < 0)
176 return r;
177
178 name = uid_to_name(uid);
179 if (!name)
180 return -ENOMEM;
181
182 p = strv_join(cmdline, " ");
183 if (!p)
184 return -ENOMEM;
185
186 /* The status string gets the full command line ... */
187 sd_notifyf(false,
188 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
189 pid, p,
190 uid, name);
191
192 /* ... and the argv line only the short comm */
193 if (arg_command_line_buffer) {
194 size_t m, w;
195
196 m = strlen(arg_command_line_buffer);
197 w = snprintf(arg_command_line_buffer, m,
198 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
199 pid, comm,
200 uid, name);
201
202 if (m > w)
203 memzero(arg_command_line_buffer + w, m - w);
204 }
205
206 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
207 pid, p,
208 uid, name,
209 a->unique_name);
210
211 return 0;
212}
213
214int main(int argc, char *argv[]) {
215 _cleanup_(proxy_freep) Proxy *p = NULL;
216 int r;
217
218 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
219 log_parse_environment();
220 log_open();
221
222 r = parse_argv(argc, argv);
223 if (r <= 0)
224 goto finish;
225
226 r = proxy_new(&p, STDIN_FILENO, STDOUT_FILENO, arg_address);
227 if (r < 0)
228 goto finish;
229
d27efd93 230 r = rename_service(p->destination_bus, p->local_bus);
f299e3e4
DH
231 if (r < 0)
232 log_debug_errno(r, "Failed to rename process: %m");
233
234 r = proxy_run(p);
235
236finish:
237 sd_notify(false,
238 "STOPPING=1\n"
239 "STATUS=Shutting down.");
240
f299e3e4
DH
241 free(arg_address);
242
243 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
244}