summaryrefslogtreecommitdiff
path: root/src/run/run.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/run/run.c')
-rw-r--r--src/run/run.c103
1 files changed, 71 insertions, 32 deletions
diff --git a/src/run/run.c b/src/run/run.c
index 148854a9b5..93d8cd1d08 100644
--- a/src/run/run.c
+++ b/src/run/run.c
@@ -19,24 +19,27 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <stdio.h>
#include <getopt.h>
+#include <stdio.h>
#include "sd-bus.h"
#include "sd-event.h"
+
+#include "bus-error.h"
#include "bus-util.h"
-#include "event-util.h"
-#include "strv.h"
-#include "build.h"
-#include "unit-name.h"
+#include "calendarspec.h"
#include "env-util.h"
+#include "event-util.h"
+#include "formats-util.h"
#include "path-util.h"
-#include "bus-error.h"
-#include "calendarspec.h"
#include "ptyfwd.h"
-#include "formats-util.h"
#include "signal-util.h"
+#include "spawn-polkit-agent.h"
+#include "strv.h"
+#include "terminal-util.h"
+#include "unit-name.h"
+static bool arg_ask_password = true;
static bool arg_scope = false;
static bool arg_remain_after_exit = false;
static bool arg_no_block = false;
@@ -60,10 +63,22 @@ static usec_t arg_on_boot = 0;
static usec_t arg_on_startup = 0;
static usec_t arg_on_unit_active = 0;
static usec_t arg_on_unit_inactive = 0;
-static char *arg_on_calendar = NULL;
+static const char *arg_on_calendar = NULL;
static char **arg_timer_property = NULL;
static bool arg_quiet = false;
+static void polkit_agent_open_if_enabled(void) {
+
+ /* Open the polkit agent as a child process if necessary */
+ if (!arg_ask_password)
+ return;
+
+ if (arg_transport != BUS_TRANSPORT_LOCAL)
+ return;
+
+ polkit_agent_open();
+}
+
static void help(void) {
printf("%s [OPTIONS...] {COMMAND} [ARGS...]\n\n"
"Run the specified command in a transient scope or service or timer\n"
@@ -71,6 +86,7 @@ static void help(void) {
"specified with --unit option then command can be omitted.\n\n"
" -h --help Show this help\n"
" --version Show package version\n"
+ " --no-ask-password Do not prompt for password\n"
" --user Run as user unit\n"
" -H --host=[USER@]HOST Operate on remote host\n"
" -M --machine=CONTAINER Operate on local container\n"
@@ -108,6 +124,7 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
+ ARG_NO_ASK_PASSWORD,
ARG_USER,
ARG_SYSTEM,
ARG_SCOPE,
@@ -160,11 +177,11 @@ static int parse_argv(int argc, char *argv[]) {
{ "on-calendar", required_argument, NULL, ARG_ON_CALENDAR },
{ "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY },
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
+ { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
{},
};
int r, c;
- CalendarSpec *spec = NULL;
assert(argc >= 0);
assert(argv);
@@ -177,10 +194,12 @@ static int parse_argv(int argc, char *argv[]) {
help();
return 0;
+ case ARG_NO_ASK_PASSWORD:
+ arg_ask_password = false;
+ break;
+
case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(SYSTEMD_FEATURES);
- return 0;
+ return version();
case ARG_USER:
arg_user = true;
@@ -316,16 +335,19 @@ static int parse_argv(int argc, char *argv[]) {
break;
- case ARG_ON_CALENDAR:
+ case ARG_ON_CALENDAR: {
+ CalendarSpec *spec = NULL;
r = calendar_spec_from_string(optarg, &spec);
if (r < 0) {
log_error("Invalid calendar spec: %s", optarg);
return r;
}
- free(spec);
+
+ calendar_spec_free(spec);
arg_on_calendar = optarg;
break;
+ }
case ARG_TIMER_PROPERTY:
@@ -370,6 +392,11 @@ static int parse_argv(int argc, char *argv[]) {
return -EINVAL;
}
+ if (arg_pty && arg_transport == BUS_TRANSPORT_REMOTE) {
+ log_error("--pty is only supported when connecting to the local system or containers.");
+ return -EINVAL;
+ }
+
if (arg_scope && with_timer()) {
log_error("Timer options are not supported in --scope mode.");
return -EINVAL;
@@ -681,13 +708,16 @@ static int start_transient_service(
if (r < 0)
return log_error_errno(r, "Failed to determine tty name: %m");
+ if (unlockpt(master) < 0)
+ return log_error_errno(errno, "Failed to unlock tty: %m");
+
} else if (arg_transport == BUS_TRANSPORT_MACHINE) {
_cleanup_bus_unref_ sd_bus *system_bus = NULL;
const char *s;
- r = sd_bus_open_system(&system_bus);
+ r = sd_bus_default_system(&system_bus);
if (r < 0)
- log_error_errno(r, "Failed to connect to system bus: %m");
+ return log_error_errno(r, "Failed to connect to system bus: %m");
r = sd_bus_call_method(system_bus,
"org.freedesktop.machine1",
@@ -717,9 +747,6 @@ static int start_transient_service(
return log_oom();
} else
assert_not_reached("Can't allocate tty via ssh");
-
- if (unlockpt(master) < 0)
- return log_error_errno(errno, "Failed to unlock tty: %m");
}
if (!arg_no_block) {
@@ -745,6 +772,10 @@ static int start_transient_service(
if (r < 0)
return bus_log_create_error(r);
+ r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
+ if (r < 0)
+ return bus_log_create_error(r);
+
/* Name and mode */
r = sd_bus_message_append(m, "ss", service, "fail");
if (r < 0)
@@ -768,11 +799,11 @@ static int start_transient_service(
if (r < 0)
return bus_log_create_error(r);
+ polkit_agent_open_if_enabled();
+
r = sd_bus_call(bus, m, 0, &error, &reply);
- if (r < 0) {
- log_error("Failed to start transient service unit: %s", bus_error_message(&error, -r));
- return r;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to start transient service unit: %s", bus_error_message(&error, r));
if (w) {
const char *object;
@@ -803,7 +834,7 @@ static int start_transient_service(
if (!arg_quiet)
log_info("Running as unit %s.\nPress ^] three times within 1s to disconnect TTY.", service);
- r = pty_forward_new(event, master, false, false, &forward);
+ r = pty_forward_new(event, master, PTY_FORWARD_IGNORE_INITIAL_VHANGUP, &forward);
if (r < 0)
return log_error_errno(r, "Failed to create PTY forwarder: %m");
@@ -860,6 +891,10 @@ static int start_transient_scope(
if (r < 0)
return bus_log_create_error(r);
+ r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
+ if (r < 0)
+ return bus_log_create_error(r);
+
/* Name and Mode */
r = sd_bus_message_append(m, "ss", scope, "fail");
if (r < 0)
@@ -883,6 +918,8 @@ static int start_transient_scope(
if (r < 0)
return bus_log_create_error(r);
+ polkit_agent_open_if_enabled();
+
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
log_error("Failed to start transient scope unit: %s", bus_error_message(&error, -r));
@@ -1025,6 +1062,10 @@ static int start_transient_timer(
if (r < 0)
return bus_log_create_error(r);
+ r = sd_bus_message_set_allow_interactive_authorization(m, arg_ask_password);
+ if (r < 0)
+ return bus_log_create_error(r);
+
/* Name and Mode */
r = sd_bus_message_append(m, "ss", timer, "fail");
if (r < 0)
@@ -1077,6 +1118,8 @@ static int start_transient_timer(
if (r < 0)
return bus_log_create_error(r);
+ polkit_agent_open_if_enabled();
+
r = sd_bus_call(bus, m, 0, &error, &reply);
if (r < 0) {
log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
@@ -1129,19 +1172,15 @@ int main(int argc, char* argv[]) {
}
if (arg_unit && isempty(description)) {
- free(description);
- description = strdup(arg_unit);
-
- if (!description) {
- r = log_oom();
+ r = free_and_strdup(&description, arg_unit);
+ if (r < 0)
goto finish;
- }
}
arg_description = description;
}
- r = bus_open_transport_systemd(arg_transport, arg_host, arg_user, &bus);
+ r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus);
if (r < 0) {
log_error_errno(r, "Failed to create bus connection: %m");
goto finish;