chiark
/
gitweb
/
~ianmdlvl
/
elogind.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
polkit: temporarily spawn of a polkit agent in terminals for possibly authenticated...
[elogind.git]
/
src
/
systemctl.c
diff --git
a/src/systemctl.c
b/src/systemctl.c
index 4b27b69c557f4e1dcacde21d8a1e77d0bafcf867..7abd928389628606fd7fbb592bf924d9391cac0d 100644
(file)
--- a/
src/systemctl.c
+++ b/
src/systemctl.c
@@
-36,6
+36,7
@@
#include <dbus/dbus.h>
#include <systemd/sd-daemon.h>
#include <dbus/dbus.h>
#include <systemd/sd-daemon.h>
+#include <systemd/sd-shutdown.h>
#include "log.h"
#include "util.h"
#include "log.h"
#include "util.h"
@@
-51,13
+52,13
@@
#include "list.h"
#include "path-lookup.h"
#include "conf-parser.h"
#include "list.h"
#include "path-lookup.h"
#include "conf-parser.h"
-#include "shutdownd.h"
#include "exit-status.h"
#include "bus-errors.h"
#include "build.h"
#include "unit-name.h"
#include "pager.h"
#include "exit-status.h"
#include "bus-errors.h"
#include "build.h"
#include "unit-name.h"
#include "pager.h"
-#include "spawn-agent.h"
+#include "spawn-ask-password-agent.h"
+#include "spawn-polkit-agent.h"
#include "install.h"
#include "logs-show.h"
#include "install.h"
#include "logs-show.h"
@@
-78,7
+79,7
@@
static bool arg_dry = false;
static bool arg_quiet = false;
static bool arg_full = false;
static int arg_force = 0;
static bool arg_quiet = false;
static bool arg_full = false;
static int arg_force = 0;
-static bool arg_ask_password =
fals
e;
+static bool arg_ask_password =
tru
e;
static bool arg_failed = false;
static bool arg_runtime = false;
static char **arg_wall = NULL;
static bool arg_failed = false;
static bool arg_runtime = false;
static char **arg_wall = NULL;
@@
-154,7
+155,7
@@
static void pager_open_if_enabled(void) {
pager_open();
}
pager_open();
}
-static void agent_open_if_enabled(void) {
+static void a
sk_password_a
gent_open_if_enabled(void) {
/* Open the password agent as a child process if necessary */
/* Open the password agent as a child process if necessary */
@@
-164,7
+165,20
@@
static void agent_open_if_enabled(void) {
if (arg_scope != UNIT_FILE_SYSTEM)
return;
if (arg_scope != UNIT_FILE_SYSTEM)
return;
- agent_open();
+ ask_password_agent_open();
+}
+
+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_scope != UNIT_FILE_SYSTEM)
+ return;
+
+ polkit_agent_open();
}
static const char *ansi_highlight_red(bool b) {
}
static const char *ansi_highlight_red(bool b) {
@@
-242,7
+256,8
@@
static void warn_wall(enum action a) {
if (arg_wall) {
char *p;
if (arg_wall) {
char *p;
- if (!(p = strv_join(arg_wall, " "))) {
+ p = strv_join(arg_wall, " ");
+ if (!p) {
log_error("Failed to join strings.");
return;
}
log_error("Failed to join strings.");
return;
}
@@
-1600,7
+1615,7
@@
static int start_unit(DBusConnection *bus, char **args) {
assert(bus);
assert(bus);
- agent_open_if_enabled();
+ a
sk_password_a
gent_open_if_enabled();
if (arg_action == ACTION_SYSTEMCTL) {
method =
if (arg_action == ACTION_SYSTEMCTL) {
method =
@@
-1682,7
+1697,8
@@
finish:
return ret;
}
return ret;
}
-/* ask systemd-logind, which might grant access to unprivileged users through polkit */
+/* Ask systemd-logind, which might grant access to unprivileged users
+ * through PolicyKit */
static int reboot_with_logind(DBusConnection *bus, enum action a) {
#ifdef HAVE_LOGIND
const char *method;
static int reboot_with_logind(DBusConnection *bus, enum action a) {
#ifdef HAVE_LOGIND
const char *method;
@@
-1693,6
+1709,8
@@
static int reboot_with_logind(DBusConnection *bus, enum action a) {
dbus_error_init(&error);
dbus_error_init(&error);
+ polkit_agent_open_if_enabled();
+
switch (a) {
case ACTION_REBOOT:
switch (a) {
case ACTION_REBOOT:
@@
-1771,16
+1789,13
@@
static int start_special(DBusConnection *bus, char **args) {
a = verb_to_action(args[0]);
a = verb_to_action(args[0]);
- if (arg_force >= 2 && a == ACTION_HALT)
- halt_now(ACTION_HALT);
-
- if (arg_force >= 2 && a == ACTION_POWEROFF)
- halt_now(ACTION_POWEROFF);
-
- if (arg_force >= 2 && a == ACTION_REBOOT)
- halt_now(ACTION_REBOOT);
+ if (arg_force >= 2 &&
+ (a == ACTION_HALT ||
+ a == ACTION_POWEROFF ||
+ a == ACTION_REBOOT))
+ halt_now(a);
- if (arg_force &&
+ if (arg_force
>= 1
&&
(a == ACTION_HALT ||
a == ACTION_POWEROFF ||
a == ACTION_REBOOT ||
(a == ACTION_HALT ||
a == ACTION_POWEROFF ||
a == ACTION_REBOOT ||
@@
-1788,14
+1803,13
@@
static int start_special(DBusConnection *bus, char **args) {
a == ACTION_EXIT))
return daemon_reload(bus, args);
a == ACTION_EXIT))
return daemon_reload(bus, args);
- if (geteuid() != 0) {
- /* first try logind, to allow authentication with polkit */
- if (a == ACTION_POWEROFF ||
- a == ACTION_REBOOT) {
- r = reboot_with_logind(bus, a);
- if (r >= 0)
- return r;
- }
+ /* first try logind, to allow authentication with polkit */
+ if (geteuid() != 0 &&
+ (a == ACTION_POWEROFF ||
+ a == ACTION_REBOOT)) {
+ r = reboot_with_logind(bus, a);
+ if (r >= 0)
+ return r;
}
r = start_unit(bus, args);
}
r = start_unit(bus, args);
@@
-4292,9
+4306,6
@@
static int systemctl_parse_argv(int argc, char *argv[]) {
assert(argc >= 0);
assert(argv);
assert(argc >= 0);
assert(argv);
- /* Only when running as systemctl we ask for passwords */
- arg_ask_password = true;
-
while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
switch (c) {
while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
switch (c) {
@@
-4630,6
+4641,7
@@
static int shutdown_parse_argv(int argc, char *argv[]) {
{ "halt", no_argument, NULL, 'H' },
{ "poweroff", no_argument, NULL, 'P' },
{ "reboot", no_argument, NULL, 'r' },
{ "halt", no_argument, NULL, 'H' },
{ "poweroff", no_argument, NULL, 'P' },
{ "reboot", no_argument, NULL, 'r' },
+ { "kexec", no_argument, NULL, 'K' }, /* not documented extension */
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
{ NULL, 0, NULL, 0 }
};
{ "no-wall", no_argument, NULL, ARG_NO_WALL },
{ NULL, 0, NULL, 0 }
};
@@
-4661,6
+4673,10
@@
static int shutdown_parse_argv(int argc, char *argv[]) {
arg_action = ACTION_REBOOT;
break;
arg_action = ACTION_REBOOT;
break;
+ case 'K':
+ arg_action = ACTION_KEXEC;
+ break;
+
case 'h':
if (arg_action != ACTION_HALT)
arg_action = ACTION_POWEROFF;
case 'h':
if (arg_action != ACTION_HALT)
arg_action = ACTION_POWEROFF;
@@
-4693,7
+4709,8
@@
static int shutdown_parse_argv(int argc, char *argv[]) {
}
if (argc > optind) {
}
if (argc > optind) {
- if ((r = parse_time_spec(argv[optind], &arg_when)) < 0) {
+ r = parse_time_spec(argv[optind], &arg_when);
+ if (r < 0) {
log_error("Failed to parse time specification: %s", argv[optind]);
return r;
}
log_error("Failed to parse time specification: %s", argv[optind]);
return r;
}
@@
-5192,39
+5209,42
@@
static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
}
static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
}
static int send_shutdownd(usec_t t, char mode, bool dry_run, bool warn, const char *message) {
- int fd
= -1
;
+ int fd;
struct msghdr msghdr;
struct msghdr msghdr;
- struct iovec iovec;
+ struct iovec iovec
[2]
;
union sockaddr_union sockaddr;
union sockaddr_union sockaddr;
- struct shutdownd_command c;
+ struct sd_shutdown_command c;
+
+ fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+ if (fd < 0)
+ return -errno;
zero(c);
zero(c);
- c.
elapse
= t;
+ c.
usec
= t;
c.mode = mode;
c.dry_run = dry_run;
c.warn_wall = warn;
c.mode = mode;
c.dry_run = dry_run;
c.warn_wall = warn;
- if (message)
- strncpy(c.wall_message, message, sizeof(c.wall_message));
-
- if ((fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0)) < 0)
- return -errno;
-
zero(sockaddr);
sockaddr.sa.sa_family = AF_UNIX;
zero(sockaddr);
sockaddr.sa.sa_family = AF_UNIX;
- sockaddr.un.sun_path[0] = 0;
strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
strncpy(sockaddr.un.sun_path, "/run/systemd/shutdownd", sizeof(sockaddr.un.sun_path));
- zero(iovec);
- iovec.iov_base = (char*) &c;
- iovec.iov_len = sizeof(c);
-
zero(msghdr);
msghdr.msg_name = &sockaddr;
msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
zero(msghdr);
msghdr.msg_name = &sockaddr;
msghdr.msg_namelen = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/systemd/shutdownd") - 1;
- msghdr.msg_iov = &iovec;
- msghdr.msg_iovlen = 1;
+ zero(iovec);
+ iovec[0].iov_base = (char*) &c;
+ iovec[0].iov_len = offsetof(struct sd_shutdown_command, wall_message);
+
+ if (isempty(message))
+ msghdr.msg_iovlen = 1;
+ else {
+ iovec[1].iov_base = (char*) message;
+ iovec[1].iov_len = strlen(message);
+ msghdr.msg_iovlen = 2;
+ }
+ msghdr.msg_iov = iovec;
if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
close_nointr_nofail(fd);
if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) {
close_nointr_nofail(fd);
@@
-5314,8
+5334,15
@@
static int halt_main(DBusConnection *bus) {
int r;
if (geteuid() != 0) {
int r;
if (geteuid() != 0) {
- if (arg_action == ACTION_POWEROFF ||
- arg_action == ACTION_REBOOT) {
+ /* Try logind if we are a normal user and no special
+ * mode applies. Maybe PolicyKit allows us to shutdown
+ * the machine. */
+
+ if (arg_when <= 0 &&
+ !arg_dry &&
+ !arg_immediate &&
+ (arg_action == ACTION_POWEROFF ||
+ arg_action == ACTION_REBOOT)) {
r = reboot_with_logind(bus, arg_action);
if (r >= 0)
return r;
r = reboot_with_logind(bus, arg_action);
if (r >= 0)
return r;
@@
-5327,12
+5354,12
@@
static int halt_main(DBusConnection *bus) {
if (arg_when > 0) {
char *m;
if (arg_when > 0) {
char *m;
- char date[FORMAT_TIMESTAMP_MAX];
m = strv_join(arg_wall, " ");
r = send_shutdownd(arg_when,
arg_action == ACTION_HALT ? 'H' :
arg_action == ACTION_POWEROFF ? 'P' :
m = strv_join(arg_wall, " ");
r = send_shutdownd(arg_when,
arg_action == ACTION_HALT ? 'H' :
arg_action == ACTION_POWEROFF ? 'P' :
+ arg_action == ACTION_KEXEC ? 'K' :
'r',
arg_dry,
!arg_no_wall,
'r',
arg_dry,
!arg_no_wall,
@@
-5342,6
+5369,8
@@
static int halt_main(DBusConnection *bus) {
if (r < 0)
log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
else {
if (r < 0)
log_warning("Failed to talk to shutdownd, proceeding with immediate shutdown: %s", strerror(-r));
else {
+ char date[FORMAT_TIMESTAMP_MAX];
+
log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
format_timestamp(date, sizeof(date), arg_when));
return 0;
log_info("Shutdown scheduled for %s, use 'shutdown -c' to cancel.",
format_timestamp(date, sizeof(date), arg_when));
return 0;
@@
-5354,8
+5383,11
@@
static int halt_main(DBusConnection *bus) {
if (!arg_no_wtmp) {
if (sd_booted() > 0)
log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
if (!arg_no_wtmp) {
if (sd_booted() > 0)
log_debug("Not writing utmp record, assuming that systemd-update-utmp is used.");
- else if ((r = utmp_put_shutdown()) < 0)
- log_warning("Failed to write utmp record: %s", strerror(-r));
+ else {
+ r = utmp_put_shutdown();
+ if (r < 0)
+ log_warning("Failed to write utmp record: %s", strerror(-r));
+ }
}
if (!arg_no_sync)
}
if (!arg_no_sync)
@@
-5395,7
+5427,8
@@
int main(int argc, char*argv[]) {
log_parse_environment();
log_open();
log_parse_environment();
log_open();
- if ((r = parse_argv(argc, argv)) < 0)
+ r = parse_argv(argc, argv);
+ if (r < 0)
goto finish;
else if (r == 0) {
retval = EXIT_SUCCESS;
goto finish;
else if (r == 0) {
retval = EXIT_SUCCESS;
@@
-5483,7
+5516,8
@@
finish:
strv_free(arg_property);
pager_close();
strv_free(arg_property);
pager_close();
- agent_close();
+ ask_password_agent_close();
+ polkit_agent_close();
return retval;
}
return retval;
}