chiark / gitweb /
Merge branch 'master' into journal
[elogind.git] / src / systemctl.c
index 604400d8fb7b9d0aa14c79297a30faa4b29e6cfd..18074402e57a11af47433943bbc132a72e22af7a 100644 (file)
@@ -66,6 +66,7 @@ static const char *arg_job_mode = "replace";
 static UnitFileScope arg_scope = UNIT_FILE_SYSTEM;
 static bool arg_immediate = false;
 static bool arg_no_block = false;
+static bool arg_no_legend = false;
 static bool arg_no_pager = false;
 static bool arg_no_wtmp = false;
 static bool arg_no_sync = false;
@@ -137,6 +138,8 @@ static bool on_tty(void) {
 }
 
 static void pager_open_if_enabled(void) {
+
+        /* Cache result before we open the pager */
         on_tty();
 
         if (arg_no_pager)
@@ -312,35 +315,60 @@ static bool output_show_unit(const struct unit_info *u) {
 }
 
 static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
-        unsigned active_len, sub_len, job_len, n_shown = 0;
+        unsigned id_len, max_id_len, active_len, sub_len, job_len, desc_len, n_shown = 0;
         const struct unit_info *u;
 
+        max_id_len = sizeof("UNIT")-1;
         active_len = sizeof("ACTIVE")-1;
         sub_len = sizeof("SUB")-1;
         job_len = sizeof("JOB")-1;
+        desc_len = 0;
 
         for (u = unit_infos; u < unit_infos + c; u++) {
                 if (!output_show_unit(u))
                         continue;
 
+                max_id_len = MAX(max_id_len, strlen(u->id));
                 active_len = MAX(active_len, strlen(u->active_state));
                 sub_len = MAX(sub_len, strlen(u->sub_state));
                 if (u->job_id != 0)
                         job_len = MAX(job_len, strlen(u->job_type));
         }
 
-        if (on_tty()) {
-                printf("%-25s %-6s %-*s %-*s %-*s", "UNIT", "LOAD",
+        if (!arg_full) {
+                unsigned basic_len;
+                id_len = MIN(max_id_len, 25);
+                basic_len = 5 + id_len + 6 + active_len + sub_len + job_len;
+                if (basic_len < (unsigned) columns()) {
+                        unsigned extra_len, incr;
+                        extra_len = columns() - basic_len;
+                        /* Either UNIT already got 25, or is fully satisfied.
+                         * Grant up to 25 to DESC now. */
+                        incr = MIN(extra_len, 25);
+                        desc_len += incr;
+                        extra_len -= incr;
+                        /* split the remaining space between UNIT and DESC,
+                         * but do not give UNIT more than it needs. */
+                        if (extra_len > 0) {
+                                incr = MIN(extra_len / 2, max_id_len - id_len);
+                                id_len += incr;
+                                desc_len += extra_len - incr;
+                        }
+                }
+        } else
+                id_len = max_id_len;
+
+        if (!arg_no_legend) {
+                printf("%-*s %-6s %-*s %-*s %-*s ", id_len, "UNIT", "LOAD",
                        active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
-                if (columns() >= 80+12 || arg_full || !arg_no_pager)
-                        printf(" %s\n", "DESCRIPTION");
+                if (!arg_full && arg_no_pager)
+                        printf("%.*s\n", desc_len, "DESCRIPTION");
                 else
-                        printf("\n");
+                        printf("%s\n", "DESCRIPTION");
         }
 
         for (u = unit_infos; u < unit_infos + c; u++) {
                 char *e;
-                int a = 0, b = 0;
                 const char *on_loaded, *off_loaded;
                 const char *on_active, *off_active;
 
@@ -362,39 +390,23 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
                 } else
                         on_active = off_active = "";
 
-                e = arg_full ? NULL : ellipsize(u->id, 25, 33);
+                e = arg_full ? NULL : ellipsize(u->id, id_len, 33);
 
-                printf("%-25s %s%-6s%s %s%-*s %-*s%s%n",
-                       e ? e : u->id,
+                printf("%-*s %s%-6s%s %s%-*s %-*s%s %-*s ",
+                       id_len, e ? e : u->id,
                        on_loaded, u->load_state, off_loaded,
                        on_active, active_len, u->active_state,
                        sub_len, u->sub_state, off_active,
-                       &a);
-
-                free(e);
-
-                a -= strlen(on_loaded) + strlen(off_loaded);
-                a -= strlen(on_active) + strlen(off_active);
-
-                if (u->job_id != 0)
-                        printf(" %-*s", job_len, u->job_type);
+                       job_len, u->job_id ? u->job_type : "");
+                if (!arg_full && arg_no_pager)
+                        printf("%.*s\n", desc_len, u->description);
                 else
-                        b = 1 + job_len;
+                        printf("%s\n", u->description);
 
-                if (a + b + 1 < columns()) {
-                        if (u->job_id == 0)
-                                printf(" %-*s", job_len, "");
-
-                        if (arg_full || !arg_no_pager)
-                                printf(" %s", u->description);
-                        else
-                                printf(" %.*s", columns() - a - b - 1, u->description);
-                }
-
-                fputs("\n", stdout);
+                free(e);
         }
 
-        if (on_tty()) {
+        if (!arg_no_legend) {
                 printf("\nLOAD   = Reflects whether the unit definition was properly loaded.\n"
                        "ACTIVE = The high-level unit activation state, i.e. generalization of SUB.\n"
                        "SUB    = The low-level unit activation state, values depend on unit type.\n"
@@ -539,11 +551,30 @@ static bool output_show_unit_file(const UnitFileList *u) {
 }
 
 static void output_unit_file_list(const UnitFileList *units, unsigned c) {
-        unsigned n_shown = 0;
+        unsigned max_id_len, id_cols, state_cols, n_shown = 0;
         const UnitFileList *u;
 
-        if (on_tty())
-                printf("%-25s %-6s\n", "UNIT FILE", "STATE");
+        max_id_len = sizeof("UNIT FILE")-1;
+        state_cols = sizeof("STATE")-1;
+        for (u = units; u < units + c; u++) {
+                if (!output_show_unit_file(u))
+                        continue;
+
+                max_id_len = MAX(max_id_len, strlen(file_name_from_path(u->path)));
+                state_cols = MAX(state_cols, strlen(unit_file_state_to_string(u->state)));
+        }
+
+        if (!arg_full) {
+                unsigned basic_cols;
+                id_cols = MIN(max_id_len, 25);
+                basic_cols = 1 + id_cols + state_cols;
+                if (basic_cols < (unsigned) columns())
+                        id_cols += MIN(columns() - basic_cols, max_id_len - id_cols);
+        } else
+                id_cols = max_id_len;
+
+        if (!arg_no_legend)
+                printf("%-*s %-*s\n", id_cols, "UNIT FILE", state_cols, "STATE");
 
         for (u = units; u < units + c; u++) {
                 char *e;
@@ -568,16 +599,16 @@ static void output_unit_file_list(const UnitFileList *units, unsigned c) {
 
                 id = file_name_from_path(u->path);
 
-                e = arg_full ? NULL : ellipsize(id, 25, 33);
+                e = arg_full ? NULL : ellipsize(id, id_cols, 33);
 
-                printf("%-25s %s%-6s%s\n",
-                       e ? e : id,
-                       on, unit_file_state_to_string(u->state), off);
+                printf("%-*s %s%-*s%s\n",
+                       id_cols, e ? e : id,
+                       on, state_cols, unit_file_state_to_string(u->state), off);
 
                 free(e);
         }
 
-        if (on_tty())
+        if (!arg_no_legend)
                 printf("\n%u unit files listed.\n", n_shown);
 }
 
@@ -608,6 +639,7 @@ static int list_unit_files(DBusConnection *bus, char **args) {
 
                 r = unit_file_get_list(arg_scope, arg_root, h);
                 if (r < 0) {
+                        unit_file_list_free(h);
                         log_error("Failed to get unit file list: %s", strerror(-r));
                         return r;
                 }
@@ -1054,7 +1086,7 @@ finish:
 }
 
 static int load_unit(DBusConnection *bus, char **args) {
-        DBusMessage *m = NULL, *reply = NULL;
+        DBusMessage *m = NULL;
         DBusError error;
         int r;
         char **name;
@@ -1065,6 +1097,7 @@ static int load_unit(DBusConnection *bus, char **args) {
         assert(args);
 
         STRV_FOREACH(name, args+1) {
+                DBusMessage *reply;
 
                 if (!(m = dbus_message_new_method_call(
                                       "org.freedesktop.systemd1",
@@ -1102,9 +1135,6 @@ finish:
         if (m)
                 dbus_message_unref(m);
 
-        if (reply)
-                dbus_message_unref(reply);
-
         dbus_error_free(&error);
 
         return r;
@@ -1794,7 +1824,7 @@ finish:
 }
 
 static int kill_unit(DBusConnection *bus, char **args) {
-        DBusMessage *m = NULL, *reply = NULL;
+        DBusMessage *m = NULL;
         int r = 0;
         DBusError error;
         char **name;
@@ -1811,6 +1841,7 @@ static int kill_unit(DBusConnection *bus, char **args) {
                 arg_kill_mode = streq(arg_kill_who, "all") ? "control-group" : "process";
 
         STRV_FOREACH(name, args+1) {
+                DBusMessage *reply;
 
                 if (!(m = dbus_message_new_method_call(
                                       "org.freedesktop.systemd1",
@@ -1850,9 +1881,6 @@ finish:
         if (m)
                 dbus_message_unref(m);
 
-        if (reply)
-                dbus_message_unref(reply);
-
         dbus_error_free(&error);
 
         return r;
@@ -2155,8 +2183,6 @@ static void print_status_info(UnitStatusInfo *i) {
 
                 printf(")%s\n", off);
 
-                on = off = NULL;
-
                 if (i->main_pid == p->pid &&
                     i->start_timestamp == p->start_timestamp &&
                     i->exit_timestamp == p->start_timestamp)
@@ -2175,7 +2201,7 @@ static void print_status_info(UnitStatusInfo *i) {
 
                         if (i->running) {
                                 char *t = NULL;
-                                get_process_name(i->main_pid, &t);
+                                get_process_comm(i->main_pid, &t);
                                 if (t) {
                                         printf(" (%s)", t);
                                         free(t);
@@ -2209,7 +2235,7 @@ static void print_status_info(UnitStatusInfo *i) {
 
                         printf(" Control: %u", (unsigned) i->control_pid);
 
-                        get_process_name(i->control_pid, &t);
+                        get_process_comm(i->control_pid, &t);
                         if (t) {
                                 printf(" (%s)", t);
                                 free(t);
@@ -3230,7 +3256,7 @@ finish:
 }
 
 static int reset_failed(DBusConnection *bus, char **args) {
-        DBusMessage *m = NULL, *reply = NULL;
+        DBusMessage *m = NULL;
         int r;
         DBusError error;
         char **name;
@@ -3242,6 +3268,7 @@ static int reset_failed(DBusConnection *bus, char **args) {
                 return daemon_reload(bus, args);
 
         STRV_FOREACH(name, args+1) {
+                DBusMessage *reply;
 
                 if (!(m = dbus_message_new_method_call(
                                       "org.freedesktop.systemd1",
@@ -3278,9 +3305,6 @@ finish:
         if (m)
                 dbus_message_unref(m);
 
-        if (reply)
-                dbus_message_unref(reply);
-
         dbus_error_free(&error);
 
         return r;
@@ -3438,7 +3462,7 @@ finish:
 static int enable_sysv_units(char **args) {
         int r = 0;
 
-#if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX))
+#if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_MEEGO) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
         const char *verb = args[0];
         unsigned f = 1, t = 1;
         LookupPaths paths;
@@ -3929,6 +3953,7 @@ static int systemctl_help(void) {
                "     --no-wall        Don't send wall message before halt/power-off/reboot\n"
                "     --no-reload      When enabling/disabling unit files, don't reload daemon\n"
                "                      configuration\n"
+               "     --no-legend      Do not print a legend (column headers and hints)\n"
                "     --no-pager       Do not pipe output into a pager\n"
                "     --no-ask-password\n"
                "                      Do not ask for system passwords\n"
@@ -4079,6 +4104,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_SYSTEM,
                 ARG_GLOBAL,
                 ARG_NO_BLOCK,
+                ARG_NO_LEGEND,
                 ARG_NO_PAGER,
                 ARG_NO_WALL,
                 ARG_ORDER,
@@ -4107,6 +4133,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "system",    no_argument,       NULL, ARG_SYSTEM    },
                 { "global",    no_argument,       NULL, ARG_GLOBAL    },
                 { "no-block",  no_argument,       NULL, ARG_NO_BLOCK  },
+                { "no-legend", no_argument,       NULL, ARG_NO_LEGEND },
                 { "no-pager",  no_argument,       NULL, ARG_NO_PAGER  },
                 { "no-wall",   no_argument,       NULL, ARG_NO_WALL   },
                 { "quiet",     no_argument,       NULL, 'q'           },
@@ -4195,6 +4222,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_no_block = true;
                         break;
 
+                case ARG_NO_LEGEND:
+                        arg_no_legend = true;
+                        break;
+
                 case ARG_NO_PAGER:
                         arg_no_pager = true;
                         break;
@@ -4427,18 +4458,6 @@ static int parse_time_spec(const char *t, usec_t *_u) {
         return 0;
 }
 
-static bool kexec_loaded(void) {
-       bool loaded = false;
-       char *s;
-
-       if (read_one_line_file("/sys/kernel/kexec_loaded", &s) >= 0) {
-               if (s[0] == '1')
-                       loaded = true;
-               free(s);
-       }
-       return loaded;
-}
-
 static int shutdown_parse_argv(int argc, char *argv[]) {
 
         enum {
@@ -4993,8 +5012,17 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                         return 0;
                 }
 
+                if (!bus) {
+                        log_error("Failed to get D-Bus connection: %s",
+                                  dbus_error_is_set(error) ? error->message : "No connection to service manager.");
+                        return -EIO;
+                }
+
+        } else {
+
                 if (!bus && !avoid_bus()) {
-                        log_error("Failed to get D-Bus connection: %s", error->message);
+                        log_error("Failed to get D-Bus connection: %s",
+                                  dbus_error_is_set(error) ? error->message : "No connection to service manager.");
                         return -EIO;
                 }
         }
@@ -5050,7 +5078,7 @@ static int reload_with_fallback(DBusConnection *bus) {
 
         if (bus) {
                 /* First, try systemd via D-Bus. */
-                if (daemon_reload(bus, NULL) > 0)
+                if (daemon_reload(bus, NULL) >= 0)
                         return 0;
         }