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