chiark / gitweb /
systemctl: style fixes for the previous patch
[elogind.git] / src / systemctl / systemctl.c
index f65bd2faa00f5d879a2e5cb5eab4a58911e9ed4c..f2da2ad604278d5bf26d7ec7ed33aee5e12a8a13 100644 (file)
@@ -1500,6 +1500,238 @@ finish:
         return r;
 }
 
+static int get_unit_path(
+                DBusConnection *bus,
+                const char *name,
+                char **unit_path) {
+
+        DBusError error;
+        DBusMessage *m = NULL, *reply = NULL;
+        char *path;
+        int r = 0;
+
+        assert(bus);
+        assert(name);
+        assert(unit_path);
+
+        dbus_error_init(&error);
+
+        m = dbus_message_new_method_call("org.freedesktop.systemd1",
+                                         "/org/freedesktop/systemd1",
+                                         "org.freedesktop.systemd1.Manager",
+                                         "GetUnit");
+        if (!m) {
+                log_error("Could not allocate message.");
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        if (!dbus_message_append_args(m,
+                                      DBUS_TYPE_STRING, &name,
+                                      DBUS_TYPE_INVALID)) {
+                log_error("Could not append arguments to message.");
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+        if (!reply) {
+                if (streq(error.name, BUS_ERROR_NO_SUCH_UNIT))
+                        r = -EINVAL;
+                else {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        r = -EIO;
+                }
+                goto finish;
+        }
+
+        if (!dbus_message_get_args(reply, &error,
+                                   DBUS_TYPE_OBJECT_PATH, &path,
+                                   DBUS_TYPE_INVALID)) {
+                log_error("Failed to parse reply: %s", bus_error_message(&error));
+                r = -EIO;
+                goto finish;
+        }
+
+        *unit_path = strdup(path);
+        if (!(*unit_path)) {
+               log_error("Failed to duplicate unit path");
+               r = -ENOMEM;
+        }
+finish:
+        if (m)
+                dbus_message_unref(m);
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return r;
+}
+
+static int is_socket_listening(
+                DBusConnection *bus,
+                const char *socket_name) {
+
+        DBusError error;
+        DBusMessage *m = NULL, *reply = NULL;
+        DBusMessageIter iter, sub;
+        char *socket_object_path = NULL;
+        const char *sub_state = NULL,
+                   *interface = "org.freedesktop.systemd1.Unit",
+                   *property = "SubState";
+        int r = 0;
+
+        assert(bus);
+        assert(socket_name);
+
+        dbus_error_init(&error);
+
+        r = get_unit_path(bus, socket_name, &socket_object_path);
+        if (r < 0)
+                goto finish;
+
+        m = dbus_message_new_method_call("org.freedesktop.systemd1",
+                                         socket_object_path,
+                                         "org.freedesktop.DBus.Properties",
+                                         "Get");
+        if (!m) {
+                log_error("Could not allocate message.");
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        if (!dbus_message_append_args(m,
+                                      DBUS_TYPE_STRING, &interface,
+                                      DBUS_TYPE_STRING, &property,
+                                      DBUS_TYPE_INVALID)) {
+                log_error("Could not append arguments to message.");
+                r = -ENOMEM;
+                goto finish;
+        }
+
+        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+        if (!reply) {
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
+                r = -EIO;
+                goto finish;
+        }
+
+        dbus_message_iter_init(reply, &iter);
+        dbus_message_iter_recurse(&iter, &sub);
+
+        if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
+                log_error("Failed to parse reply: %s", bus_error_message(&error));
+                r = -EIO;
+                goto finish;
+        }
+        dbus_message_iter_get_basic(&sub, &sub_state);
+        r = streq(sub_state, "listening");
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        free(socket_object_path);
+        return r;
+}
+
+static void check_listening_sockets(
+                DBusConnection *bus,
+                const char *unit_name) {
+
+        DBusError error;
+        DBusMessage *m = NULL, *reply = NULL;
+        DBusMessageIter iter, sub;
+        const char *service_trigger = NULL,
+                   *interface = "org.freedesktop.systemd1.Unit",
+                   *triggered_by_property = "TriggeredBy";
+
+        char *unit_path = NULL;
+        bool print_warning_label = true;
+
+        dbus_error_init(&error);
+
+        if (get_unit_path(bus, unit_name, &unit_path) < 0)
+                goto finish;
+
+        m = dbus_message_new_method_call("org.freedesktop.systemd1",
+                                         unit_path,
+                                         "org.freedesktop.DBus.Properties",
+                                         "Get");
+        if (!m) {
+                log_error("Could not allocate message.");
+                goto finish;
+        }
+
+        if (!dbus_message_append_args(m,
+                                      DBUS_TYPE_STRING, &interface,
+                                      DBUS_TYPE_STRING, &triggered_by_property,
+                                      DBUS_TYPE_INVALID)) {
+                log_error("Could not append arguments to message.");
+                goto finish;
+        }
+
+        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+        if (!reply) {
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
+                goto finish;
+        }
+
+        if (!dbus_message_iter_init(reply, &iter) ||
+            dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
+                log_error("Failed to parse reply: %s", bus_error_message(&error));
+                goto finish;
+
+        }
+
+        dbus_message_iter_recurse(&iter, &sub);
+        dbus_message_iter_recurse(&sub, &iter);
+        sub = iter;
+
+        while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+                int r;
+
+                if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
+                        log_error("Failed to parse reply: %s", bus_error_message(&error));
+                        goto finish;
+                }
+
+                dbus_message_iter_get_basic(&sub, &service_trigger);
+
+                if (!endswith(service_trigger, ".socket"))
+                        goto next;
+
+                r = is_socket_listening(bus, service_trigger);
+                if (r < 0)
+                        goto finish;
+                if (r == 1) {
+                        if (print_warning_label) {
+                                log_warning("There are listening sockets associated with %s :", unit_name);
+                                print_warning_label = false;
+                        }
+                        log_warning("%s", service_trigger);
+                }
+next:
+                dbus_message_iter_recurse(&iter, &sub);
+                iter = sub;
+        }
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        free(unit_path);
+}
+
 static int start_unit_one(
                 DBusConnection *bus,
                 const char *method,
@@ -1580,6 +1812,10 @@ static int start_unit_one(
                 }
         }
 
+        /* When stopping unit check if we have some listening sockets active */
+        if (streq(method, "StopUnit") && !arg_quiet)
+                check_listening_sockets(bus, name);
+
         r = 0;
 
 finish:
@@ -2458,7 +2694,7 @@ static void print_status_info(UnitStatusInfo *i) {
                        arg_scope == UNIT_FILE_SYSTEM ? "--system" : "--user");
 }
 
-static void man_status_info(UnitStatusInfo *i) {
+static void show_unit_help(UnitStatusInfo *i) {
         char **p;
 
         assert(i);
@@ -3020,8 +3256,8 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo
         r = 0;
 
         if (!show_properties) {
-                if (streq(verb, "man"))
-                        man_status_info(&info);
+                if (streq(verb, "help"))
+                        show_unit_help(&info);
                 else
                         print_status_info(&info);
         }
@@ -4284,7 +4520,7 @@ static int systemctl_help(void) {
                "  status [NAME...|PID...]         Show runtime status of one or more units\n"
                "  show [NAME...|JOB...]           Show properties of one or more\n"
                "                                  units/jobs or the manager\n"
-               "  man [NAME...|PID...]            Show manual for one or more units\n"
+               "  help [NAME...|PID...]            Show manual for one or more units\n"
                "  reset-failed [NAME...]          Reset failed state for all, one, or more\n"
                "                                  units\n"
                "  load [NAME...]                  Load one or more units\n\n"
@@ -5248,7 +5484,7 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 { "check",                 MORE,  2, check_unit        },
                 { "show",                  MORE,  1, show              },
                 { "status",                MORE,  2, show              },
-                { "man",                   MORE,  2, show              },
+                { "help",                  MORE,  2, show              },
                 { "dump",                  EQUAL, 1, dump              },
                 { "dot",                   EQUAL, 1, dot               },
                 { "snapshot",              LESS,  2, snapshot          },
@@ -5293,9 +5529,10 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 /* Special rule: no arguments means "list-units" */
                 i = 0;
         else {
-                if (streq(argv[optind], "help")) {
-                        systemctl_help();
-                        return 0;
+                if (streq(argv[optind], "help") && !argv[optind+1]) {
+                        log_error("This command expects one or more "
+                                  "unit names. Did you mean --help?");
+                        return -EINVAL;
                 }
 
                 for (i = 0; i < ELEMENTSOF(verbs); i++)