run.c revision e3e0314b56012f7febc279d268f2cadc1fcc0f25
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering/***
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering This file is part of systemd.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering Copyright 2013 Lennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering systemd is free software; you can redistribute it and/or modify it
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering under the terms of the GNU Lesser General Public License as published by
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering (at your option) any later version.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering systemd is distributed in the hope that it will be useful, but
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering Lesser General Public License for more details.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU Lesser General Public License
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering***/
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering#include <stdio.h>
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering#include <getopt.h>
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "sd-bus.h"
cf0fbc49e67b55f8d346fc94de28c90113505297Thomas Hindoe Paaboel Andersen#include "bus-util.h"
0284adc6a60ce0af1107cb0b50041a65d731f39eLennart Poettering#include "strv.h"
cf0fbc49e67b55f8d346fc94de28c90113505297Thomas Hindoe Paaboel Andersen#include "build.h"
cf0fbc49e67b55f8d346fc94de28c90113505297Thomas Hindoe Paaboel Andersen#include "unit-name.h"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering#include "path-util.h"
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek#include "bus-error.h"
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmekstatic bool arg_scope = false;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic bool arg_remain_after_exit = false;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic const char *arg_unit = NULL;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic const char *arg_description = NULL;
3c1668da6202f1ead3d4d3981b89e9da1a0e98e3Lennart Poetteringstatic const char *arg_slice = NULL;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic bool arg_send_sighup = false;
de190aef08bb267b645205a747762df573b36834Lennart Poetteringstatic BusTransport arg_transport = BUS_TRANSPORT_LOCAL;
95ea1b90cc61f464f3b9bc147119dee4ba9620b8Lennart Poetteringstatic char *arg_host = NULL;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic bool arg_user = false;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poetteringstatic int help(void) {
95ea1b90cc61f464f3b9bc147119dee4ba9620b8Lennart Poettering
95ea1b90cc61f464f3b9bc147119dee4ba9620b8Lennart Poettering printf("%s [OPTIONS...] COMMAND [ARGS...]\n\n"
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering "Run the specified command in a transient scope or service unit.\n\n"
16e9f408fa9a9626059bdd6c89dc175e06b9e976Lennart Poettering " -h --help Show this help\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " --version Show package version\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " --user Run as user unit\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " -H --host=[USER@]HOST Operate on remote host\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " -M --machine=CONTAINER Operate on local container\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " --scope Run this as scope rather than service\n"
c2373f848dddcc1827cf715c5ef778dc8d475761Lennart Poettering " --unit=UNIT Run under the specified unit name\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " --description=TEXT Description for unit\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " --slice=SLICE Run in the specified slice\n"
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering " -r --remain-after-exit Leave service around until explicitly stopped\n"
c2373f848dddcc1827cf715c5ef778dc8d475761Lennart Poettering " --send-sighup Send SIGHUP when terminating\n",
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering program_invocation_short_name);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering return 0;
c2373f848dddcc1827cf715c5ef778dc8d475761Lennart Poettering}
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poetteringstatic int parse_argv(int argc, char *argv[]) {
b0af6f41ea67c97b8beb16fd1d63042379bbf103Lennart Poettering
feb12d3ed2c7f9132c64773c7c41b9e3a608a814Lennart Poettering enum {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering ARG_VERSION = 0x100,
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering ARG_USER,
f534928ad7aaeec0bec2d653b4a50e79b0fc8418Michal Schmidt ARG_SYSTEM,
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier ARG_SCOPE,
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering ARG_UNIT,
f534928ad7aaeec0bec2d653b4a50e79b0fc8418Michal Schmidt ARG_DESCRIPTION,
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier ARG_SLICE,
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering ARG_SEND_SIGHUP,
f534928ad7aaeec0bec2d653b4a50e79b0fc8418Michal Schmidt };
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering static const struct option options[] = {
f534928ad7aaeec0bec2d653b4a50e79b0fc8418Michal Schmidt { "help", no_argument, NULL, 'h' },
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering { "version", no_argument, NULL, ARG_VERSION },
f534928ad7aaeec0bec2d653b4a50e79b0fc8418Michal Schmidt { "user", no_argument, NULL, ARG_USER },
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier { "system", no_argument, NULL, ARG_SYSTEM },
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering { "scope", no_argument, NULL, ARG_SCOPE },
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier { "unit", required_argument, NULL, ARG_UNIT },
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier { "description", required_argument, NULL, ARG_DESCRIPTION },
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier { "slice", required_argument, NULL, ARG_SLICE },
de190aef08bb267b645205a747762df573b36834Lennart Poettering { "remain-after-exit", no_argument, NULL, 'r' },
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier { "send-sighup", no_argument, NULL, ARG_SEND_SIGHUP },
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier { "host", required_argument, NULL, 'H' },
de190aef08bb267b645205a747762df573b36834Lennart Poettering { "machine", required_argument, NULL, 'M' },
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier {},
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier };
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering int c;
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier assert(argc >= 0);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering assert(argv);
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering while ((c = getopt_long(argc, argv, "+hrH:M:", options, NULL)) >= 0) {
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier switch (c) {
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier case 'h':
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier return help();
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier case ARG_VERSION:
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier puts(PACKAGE_STRING);
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering puts(SYSTEMD_FEATURES);
787784c4c1b24a13207d18b415d60483cfbdeaa3Ronny Chevalier return 0;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering case ARG_USER:
7560fffcd2531786b9c1ca657667a43e90331326Lennart Poettering arg_user = true;
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering break;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering case ARG_SYSTEM:
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_user = false;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek break;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek case ARG_SCOPE:
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_scope = true;
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering break;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
c6878637502b1717a110a9a7e8bba32a8583fcdfLennart Poettering case ARG_UNIT:
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_unit = optarg;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek break;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek case ARG_DESCRIPTION:
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_description = optarg;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek break;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek case ARG_SLICE:
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_slice = optarg;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek break;
0ac38b707212e9aa40e25d65ffbae648cc9116f5Lennart Poettering
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek case ARG_SEND_SIGHUP:
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_send_sighup = true;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek break;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek case 'r':
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_remain_after_exit = true;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek break;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek case 'H':
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_transport = BUS_TRANSPORT_REMOTE;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_host = optarg;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek break;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek case 'M':
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_transport = BUS_TRANSPORT_CONTAINER;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek arg_host = optarg;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek break;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek case '?':
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek return -EINVAL;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek default:
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek assert_not_reached("Unhandled option");
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek }
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek }
8580d1f73db36e9383e674e388b4fb55828c0c66Lennart Poettering
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek if (optind >= argc) {
c6878637502b1717a110a9a7e8bba32a8583fcdfLennart Poettering log_error("Command line to execute required.");
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek return -EINVAL;
510b857f7d1e7e8d38912890536342dd5dd647ddLennart Poettering }
510b857f7d1e7e8d38912890536342dd5dd647ddLennart Poettering
510b857f7d1e7e8d38912890536342dd5dd647ddLennart Poettering if (arg_user && arg_transport != BUS_TRANSPORT_LOCAL) {
510b857f7d1e7e8d38912890536342dd5dd647ddLennart Poettering log_error("Execution in user context is not supported on non-local systems.");
510b857f7d1e7e8d38912890536342dd5dd647ddLennart Poettering return -EINVAL;
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek }
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek if (arg_scope && arg_transport != BUS_TRANSPORT_LOCAL) {
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek log_error("Scope execution is not supported on non-local systems.");
6ad1d1c30621280bfad3e63fcc1c7ceb7d8ffa98Lennart Poettering return -EINVAL;
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther }
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther return 1;
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther}
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmek
6eb7a9a0010d035e5bdbbf70227088ce02b2120eZbigniew Jędrzejewski-Szmekstatic int message_start_transient_unit_new(sd_bus *bus, const char *name, sd_bus_message **ret) {
95ea1b90cc61f464f3b9bc147119dee4ba9620b8Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering int r;
87d2c1ff6a7375f03476767e6f59454bcc5cd04bLennart Poettering
assert(bus);
assert(name);
assert(ret);
log_info("Running as unit %s.", name);
r = sd_bus_message_new_method_call(
bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartTransientUnit", &m);
if (r < 0)
return r;
r = sd_bus_message_append(m, "ss", name, "fail");
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'a', "(sv)");
if (r < 0)
return r;
r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
if (r < 0)
return r;
if (!isempty(arg_slice)) {
_cleanup_free_ char *slice;
slice = unit_name_mangle_with_suffix(arg_slice, false, ".slice");
if (!slice)
return -ENOMEM;
r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
if (r < 0)
return r;
}
r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", arg_send_sighup);
if (r < 0)
return r;
*ret = m;
m = NULL;
return 0;
}
static int message_start_transient_unit_send(sd_bus *bus, sd_bus_message *m, sd_bus_error *error, sd_bus_message **reply) {
int r;
assert(bus);
assert(m);
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
r = sd_bus_message_append(m, "a(sa(sv))", 0);
if (r < 0)
return r;
return sd_bus_call(bus, m, 0, error, reply);
}
static int start_transient_service(
sd_bus *bus,
char **argv,
sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
_cleanup_free_ char *name = NULL;
char **i;
int r;
if (arg_unit)
name = unit_name_mangle_with_suffix(arg_unit, false, ".service");
else
asprintf(&name, "run-%lu.service", (unsigned long) getpid());
if (!name)
return -ENOMEM;
r = message_start_transient_unit_new(bus, name, &m);
if (r < 0)
return r;
r = sd_bus_message_append(m, "(sv)", "RemainAfterExit", "b", arg_remain_after_exit);
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'r', "sv");
if (r < 0)
return r;
r = sd_bus_message_append(m, "s", "ExecStart");
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'v', "a(sasb)");
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'a', "(sasb)");
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'r', "sasb");
if (r < 0)
return r;
r = sd_bus_message_append(m, "s", argv[0]);
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return r;
STRV_FOREACH(i, argv) {
r = sd_bus_message_append(m, "s", *i);
if (r < 0)
return r;
}
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
r = sd_bus_message_append(m, "b", false);
if (r < 0)
return r;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
return message_start_transient_unit_send(bus, m, error, NULL);
}
static int start_transient_scope(
sd_bus *bus,
char **argv,
sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL;
_cleanup_free_ char *name = NULL;
int r;
assert(bus);
if (arg_unit)
name = unit_name_mangle_with_suffix(arg_unit, false, ".scope");
else
asprintf(&name, "run-%lu.scope", (unsigned long) getpid());
if (!name)
return -ENOMEM;
r = message_start_transient_unit_new(bus, name, &m);
if (r < 0)
return r;
r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, (uint32_t) getpid());
if (r < 0)
return r;
r = message_start_transient_unit_send(bus, m, error, NULL);
if (r < 0)
return r;
execvp(argv[0], argv);
log_error("Failed to execute: %m");
return -errno;
}
int main(int argc, char* argv[]) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_unref_ sd_bus *bus = NULL;
_cleanup_free_ char *description = NULL, *command = NULL;
int r;
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = find_binary(argv[optind], &command);
if (r < 0) {
log_error("Failed to find executable %s: %s", argv[optind], strerror(-r));
goto finish;
}
argv[optind] = command;
if (!arg_description) {
description = strv_join(argv + optind, " ");
if (!description) {
r = log_oom();
goto finish;
}
arg_description = description;
}
r = bus_open_transport(arg_transport, arg_host, arg_user, &bus);
if (r < 0) {
log_error("Failed to create bus connection: %s", strerror(-r));
goto finish;
}
if (arg_scope)
r = start_transient_scope(bus, argv + optind, &error);
else
r = start_transient_service(bus, argv + optind, &error);
if (r < 0)
log_error("Failed start transient unit: %s", bus_error_message(&error, r));
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}