chiark / gitweb /
systemctl: always disable color when output goes into a file
[elogind.git] / src / systemctl.c
index acb89a5a8767719027acaf279dd5d3f47dbd9652..d78294b6d8da2d064e5b4d0823981c6a2bc4d556 100644 (file)
@@ -58,6 +58,7 @@ static bool arg_no_sync = false;
 static bool arg_no_wall = false;
 static bool arg_dry = false;
 static bool arg_quiet = false;
+static char arg_full = false;
 static char **arg_wall = NULL;
 static enum action {
         ACTION_INVALID,
@@ -85,6 +86,18 @@ static enum dot {
 
 static bool private_bus = false;
 
+static const char *ansi_highlight(bool b) {
+        static int t = -1;
+
+        if (_unlikely_(t < 0))
+                t = isatty(STDOUT_FILENO) > 0;
+
+        if (!t)
+                return "";
+
+        return b ? ANSI_HIGHLIGHT_ON : ANSI_HIGHLIGHT_OFF;
+}
+
 static bool error_is_no_service(DBusError *error) {
 
         assert(error);
@@ -192,7 +205,7 @@ static int list_units(DBusConnection *bus, char **args, unsigned n) {
                 printf("%-45s %-6s %-12s %-12s %-15s %s\n", "UNIT", "LOAD", "ACTIVE", "SUB", "JOB", "DESCRIPTION");
 
         while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
-                const char *id, *description, *load_state, *active_state, *sub_state, *unit_path, *job_type, *job_path, *dot;
+                const char *id, *description, *load_state, *active_state, *sub_state, *following, *unit_path, *job_type, *job_path, *dot;
                 uint32_t job_id;
 
                 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
@@ -208,6 +221,7 @@ static int list_units(DBusConnection *bus, char **args, unsigned n) {
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &load_state, true) < 0 ||
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &active_state, true) < 0 ||
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &sub_state, true) < 0 ||
+                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &following, true) < 0 ||
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path, true) < 0 ||
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &job_id, true) < 0 ||
                     bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &job_type, true) < 0 ||
@@ -219,14 +233,16 @@ static int list_units(DBusConnection *bus, char **args, unsigned n) {
 
                 if ((!arg_type || ((dot = strrchr(id, '.')) &&
                                    streq(dot+1, arg_type))) &&
-                    (arg_all || !streq(active_state, "inactive") || job_id > 0)) {
-
+                    (arg_all || !(streq(active_state, "inactive") || following[0]) || job_id > 0)) {
+                        char *e;
                         int a = 0, b = 0;
 
                         if (streq(active_state, "maintenance"))
-                                fputs(ANSI_HIGHLIGHT_ON, stdout);
+                                fputs(ansi_highlight(true), stdout);
 
-                        printf("%-45s %-6s %-12s %-12s%n", id, load_state, active_state, sub_state, &a);
+                        e = arg_full ? NULL : ellipsize(id, 45, 33);
+                        printf("%-45s %-6s %-12s %-12s%n", e ? e : id, load_state, active_state, sub_state, &a);
+                        free(e);
 
                         if (job_id != 0)
                                 printf(" => %-12s%n", job_type, &b);
@@ -241,7 +257,7 @@ static int list_units(DBusConnection *bus, char **args, unsigned n) {
                         }
 
                         if (streq(active_state, "maintenance"))
-                                fputs(ANSI_HIGHLIGHT_OFF, stdout);
+                                fputs(ansi_highlight(false), stdout);
 
                         fputs("\n", stdout);
                         k++;
@@ -558,6 +574,7 @@ static int list_jobs(DBusConnection *bus, char **args, unsigned n) {
         while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
                 const char *name, *type, *state, *job_path, *unit_path;
                 uint32_t id;
+                char *e;
 
                 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) {
                         log_error("Failed to parse reply.");
@@ -578,7 +595,10 @@ static int list_jobs(DBusConnection *bus, char **args, unsigned n) {
                         goto finish;
                 }
 
-                printf("%4u %-45s %-17s %-7s\n", id, name, type, state);
+                e = arg_full ? NULL : ellipsize(name, 45, 33);
+                printf("%4u %-45s %-17s %-7s\n", id, e ? e : name, type, state);
+                free(e);
+
                 k++;
 
                 dbus_message_iter_next(&sub);
@@ -1414,18 +1434,25 @@ static void print_status_info(UnitStatusInfo *i) {
         if (i->fragment_path)
                 printf("\t  Loaded: %s (%s)\n", strna(i->load_state), i->fragment_path);
         else if (streq_ptr(i->load_state, "failed"))
-                printf("\t  Loaded: " ANSI_HIGHLIGHT_ON "%s" ANSI_HIGHLIGHT_OFF "\n", strna(i->load_state));
+                printf("\t  Loaded: %s%s%s\n",
+                       ansi_highlight(true),
+                       strna(i->load_state),
+                       ansi_highlight(false));
         else
                 printf("\t  Loaded: %s\n", strna(i->load_state));
 
         if (streq_ptr(i->active_state, "maintenance")) {
                         if (streq_ptr(i->active_state, i->sub_state))
-                                printf("\t  Active: " ANSI_HIGHLIGHT_ON "%s" ANSI_HIGHLIGHT_OFF "\n",
-                                       strna(i->active_state));
+                                printf("\t  Active: %s%s%s\n",
+                                       ansi_highlight(true),
+                                       strna(i->active_state),
+                                       ansi_highlight(false));
                         else
-                                printf("\t  Active: " ANSI_HIGHLIGHT_ON "%s (%s)" ANSI_HIGHLIGHT_OFF "\n",
+                                printf("\t  Active: %s%s (%s)%s\n",
+                                       ansi_highlight(true),
                                        strna(i->active_state),
-                                       strna(i->sub_state));
+                                       strna(i->sub_state),
+                                       ansi_highlight(false));
         } else {
                 if (streq_ptr(i->active_state, i->sub_state))
                         printf("\t  Active: %s\n",
@@ -1493,8 +1520,7 @@ static void print_status_info(UnitStatusInfo *i) {
                                         printf("status=%i", i->exit_status);
                                 else
                                         printf("signal=%s", signal_to_string(i->exit_status));
-                                printf(")");
-                        }
+                                printf(")");                        }
                 }
 
                 if (i->main_pid > 0 && i->control_pid > 0)
@@ -1532,7 +1558,9 @@ static void print_status_info(UnitStatusInfo *i) {
         }
 
         if (i->need_daemon_reload)
-                printf("\n" ANSI_HIGHLIGHT_ON "Warning:" ANSI_HIGHLIGHT_OFF " Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
+                printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
+                       ansi_highlight(true),
+                       ansi_highlight(false),
                        arg_session ? "--session" : "--system");
 }
 
@@ -2895,6 +2923,7 @@ static int systemctl_help(void) {
                "  -t --type=TYPE     List only units of a particular type\n"
                "  -p --property=NAME Show only properties by this name\n"
                "  -a --all           Show all units/properties, including dead/empty ones\n"
+               "     --full          Don't ellipsize unit names.\n"
                "     --fail          When installing a new job, fail if conflicting jobs are\n"
                "                     pending\n"
                "     --system        Connect to system bus\n"
@@ -3022,7 +3051,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_NO_BLOCK,
                 ARG_NO_WALL,
                 ARG_ORDER,
-                ARG_REQUIRE
+                ARG_REQUIRE,
+                ARG_FULL
         };
 
         static const struct option options[] = {
@@ -3030,6 +3060,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "type",      required_argument, NULL, 't'          },
                 { "property",  required_argument, NULL, 'p'          },
                 { "all",       no_argument,       NULL, 'a'          },
+                { "full",      no_argument,       NULL, ARG_FULL     },
                 { "fail",      no_argument,       NULL, ARG_FAIL     },
                 { "session",   no_argument,       NULL, ARG_SESSION  },
                 { "system",    no_argument,       NULL, ARG_SYSTEM   },
@@ -3099,6 +3130,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_dot = DOT_REQUIRE;
                         break;
 
+                case ARG_FULL:
+                        arg_full = true;
+                        break;
+
                 case 'q':
                         arg_quiet = true;
                         break;