chiark / gitweb /
relicense to LGPLv2.1 (with exceptions)
[elogind.git] / src / systemctl.c
index 3cab0dd85a073cea185279a62514f34629593db9..28bdfa96a4e06d9b9c393e7b3357dd96b28f79e8 100644 (file)
@@ -6,16 +6,16 @@
   Copyright 2010 Lennart Poettering
 
   systemd is free software; you can redistribute it and/or modify it
-  under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
+  under the terms of the GNU Lesser General Public License as published by
+  the Free Software Foundation; either version 2.1 of the License, or
   (at your option) any later version.
 
   systemd is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  General Public License for more details.
+  Lesser General Public License for more details.
 
-  You should have received a copy of the GNU General Public License
+  You should have received a copy of the GNU Lesser General Public License
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
@@ -36,6 +36,7 @@
 #include <dbus/dbus.h>
 
 #include <systemd/sd-daemon.h>
+#include <systemd/sd-shutdown.h>
 
 #include "log.h"
 #include "util.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 "spawn-agent.h"
+#include "spawn-ask-password-agent.h"
+#include "spawn-polkit-agent.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_ask_password = false;
+static bool arg_ask_password = true;
 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();
 }
 
-static void agent_open_if_enabled(void) {
+static void ask_password_agent_open_if_enabled(void) {
 
         /* 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;
 
-        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) {
@@ -1601,7 +1615,7 @@ static int start_unit(DBusConnection *bus, char **args) {
 
         assert(bus);
 
-        agent_open_if_enabled();
+        ask_password_agent_open_if_enabled();
 
         if (arg_action == ACTION_SYSTEMCTL) {
                 method =
@@ -1695,6 +1709,8 @@ static int reboot_with_logind(DBusConnection *bus, enum action a) {
 
         dbus_error_init(&error);
 
+        polkit_agent_open_if_enabled();
+
         switch (a) {
 
         case ACTION_REBOOT:
@@ -4290,9 +4306,6 @@ static int systemctl_parse_argv(int argc, char *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) {
@@ -4628,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'         },
+                { "kexec",     no_argument,       NULL, 'K'         }, /* not documented extension */
                 { "no-wall",   no_argument,       NULL, ARG_NO_WALL },
                 { NULL,        0,                 NULL, 0           }
         };
@@ -4659,6 +4673,10 @@ static int shutdown_parse_argv(int argc, char *argv[]) {
                                 arg_action = ACTION_REBOOT;
                         break;
 
+                case 'K':
+                        arg_action = ACTION_KEXEC;
+                        break;
+
                 case 'h':
                         if (arg_action != ACTION_HALT)
                                 arg_action = ACTION_POWEROFF;
@@ -5191,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) {
-        int fd = -1;
+        int fd;
         struct msghdr msghdr;
-        struct iovec iovec;
+        struct iovec iovec[2];
         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);
-        c.elapse = t;
+        c.usec = t;
         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;
-        sockaddr.un.sun_path[0] = 0;
         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;
 
-        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);
@@ -5338,6 +5359,7 @@ static int halt_main(DBusConnection *bus) {
                 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,
@@ -5405,7 +5427,8 @@ int main(int argc, char*argv[]) {
         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;
@@ -5493,7 +5516,8 @@ finish:
         strv_free(arg_property);
 
         pager_close();
-        agent_close();
+        ask_password_agent_close();
+        polkit_agent_close();
 
         return retval;
 }