[systemd-commits] 3 commits - man/systemctl.xml src/pager.c src/systemctl.c

Michal Schmidt michich at kemper.freedesktop.org
Tue Sep 27 03:13:48 PDT 2011


 man/systemctl.xml |    8 +++++
 src/pager.c       |   18 +++++++++--
 src/systemctl.c   |   83 +++++++++++++++++++++++++++++++-----------------------
 3 files changed, 71 insertions(+), 38 deletions(-)

New commits:
commit 4deb3b9391167abfc661dcc43b72c16f6da52861
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Tue Sep 27 11:20:20 2011 +0200

    systemctl: better width and alignment of fields
    
    Provide nicer output by taking advantage of the available columns.
    
    Expand UNIT and DESCRIPTION if possible. Economize the space:
     - never give UNIT more width than it can use.
     - if there's a shortage of space, give 25 columns to UNIT, even
       if it would result in overflowing the total columns. The field would not
       be useful below width 25.
     - then if possible, assign up to 25 columns to DESCRIPTION.
     - then split any remaining space evenly between UNIT and DESCRIPTION.
    
    Keep the columns aligned even with '--full'.

diff --git a/src/systemctl.c b/src/systemctl.c
index 7c2b341..848d6a8 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -315,35 +315,59 @@ 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 (!arg_no_legend) {
-                printf("%-25s %-6s %-*s %-*s %-*s", "UNIT", "LOAD",
-                       active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
-                if (columns() >= 80+12 || arg_full || !arg_no_pager)
-                        printf(" %s\n", "DESCRIPTION");
-                else
-                        printf("\n");
-        }
+        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_full || !arg_no_pager)
+                desc_len = INT_MAX;
+
+        if (!arg_no_legend)
+                printf("%-*s %-6s %-*s %-*s %-*s %.*s\n", id_len, "UNIT", "LOAD",
+                       active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB",
+                       desc_len, "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;
 
@@ -365,36 +389,17 @@ 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 %.*s\n",
+                       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);
+                       job_len, u->job_id ? u->job_type : "",
+                       desc_len, u->description);
 
                 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);
-                else
-                        b = 1 + job_len;
-
-                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);
         }
 
         if (!arg_no_legend) {

commit ebed32bfe832071cde95f6adc01b1097ff079c90
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Tue Sep 27 00:48:40 2011 +0200

    systemctl: print the legend regardless of stdout type, add --no-legend
    
    Print the legend (the column headers and the footer with hints) by
    default even to non-tty output. People seem to get confused by the
    difference when they redirect the output.
    
    Add a parameter to suppress the printing of the legend.
    
    Related-to: https://bugzilla.redhat.com/show_bug.cgi?id=713567

diff --git a/man/systemctl.xml b/man/systemctl.xml
index 468141c..2ea6fe9 100644
--- a/man/systemctl.xml
+++ b/man/systemctl.xml
@@ -198,6 +198,14 @@
                         </varlistentry>
 
                         <varlistentry>
+                                <term><option>--no-legend</option></term>
+
+				<listitem><para>Do not print a legend, i.e.
+                                the column headers and the footer with hints.
+				</para></listitem>
+			</varlistentry>
+
+                        <varlistentry>
                                 <term><option>--no-pager</option></term>
 
 				<listitem><para>Do not pipe output into a
diff --git a/src/systemctl.c b/src/systemctl.c
index 2bf2b69..7c2b341 100644
--- a/src/systemctl.c
+++ b/src/systemctl.c
@@ -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;
@@ -331,7 +332,7 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
                         job_len = MAX(job_len, strlen(u->job_type));
         }
 
-        if (on_tty()) {
+        if (!arg_no_legend) {
                 printf("%-25s %-6s %-*s %-*s %-*s", "UNIT", "LOAD",
                        active_len, "ACTIVE", sub_len, "SUB", job_len, "JOB");
                 if (columns() >= 80+12 || arg_full || !arg_no_pager)
@@ -396,7 +397,7 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
                 fputs("\n", stdout);
         }
 
-        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"
@@ -3924,6 +3925,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"
@@ -4074,6 +4076,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,
@@ -4102,6 +4105,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'           },
@@ -4190,6 +4194,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;

commit 4a8e40ebd0938850d326c33a3d563c6cd44d47b4
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Mon Sep 26 23:02:56 2011 +0200

    pager: add a trivial internal pager
    
    In the very unlikely scenario where none of the external pagers is
    available, use an internal implementation to pass stdin to stdout.
    
    Don't bother with trying 'cat', because it's no more useful than the
    internal pager.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=713707

diff --git a/src/pager.c b/src/pager.c
index be284da..6e2bb49 100644
--- a/src/pager.c
+++ b/src/pager.c
@@ -20,6 +20,7 @@
 ***/
 
 #include <sys/types.h>
+#include <fcntl.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
@@ -31,6 +32,18 @@
 
 static pid_t pager_pid = 0;
 
+static void pager_fallback(void) {
+        ssize_t n;
+        do {
+                n = splice(STDIN_FILENO, NULL, STDOUT_FILENO, NULL, 64*1024, 0);
+        } while (n > 0);
+        if (n < 0) {
+                log_error("Internal pager failed: %m");
+                _exit(EXIT_FAILURE);
+        }
+        _exit(EXIT_SUCCESS);
+}
+
 void pager_open(void) {
         int fd[2];
         const char *pager;
@@ -96,10 +109,9 @@ void pager_open(void) {
 
                 execlp("less", "less", NULL);
                 execlp("more", "more", NULL);
-                execlp("cat", "cat", NULL);
 
-                log_error("Unable to execute pager: %m");
-                _exit(EXIT_FAILURE);
+                pager_fallback();
+                /* not reached */
         }
 
         /* Return in the parent */



More information about the systemd-commits mailing list