diff options
author | Thomas Haller <thaller@redhat.com> | 2017-05-15 23:24:37 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2017-05-15 23:25:14 +0200 |
commit | ae81216ae0cd9b4533b803656e9933f88b77990b (patch) | |
tree | f041268c21b5100878352f072cf00ec8f6f47aa7 | |
parent | f8316a536cdaa22a25acaf265c6c1160e07076e2 (diff) | |
parent | 7c24a2cb39805d413b8d07f0b2e5dfa858b8eec2 (diff) | |
download | NetworkManager-ae81216ae0cd9b4533b803656e9933f88b77990b.tar.gz |
merge: cli pager
-rw-r--r-- | clients/cli/connections.c | 37 | ||||
-rw-r--r-- | clients/cli/general.c | 5 | ||||
-rw-r--r-- | clients/cli/nmcli.c | 227 | ||||
-rw-r--r-- | clients/cli/nmcli.h | 3 | ||||
-rw-r--r-- | clients/cli/utils.c | 112 | ||||
-rw-r--r-- | clients/cli/utils.h | 4 |
6 files changed, 288 insertions, 100 deletions
diff --git a/clients/cli/connections.c b/clients/cli/connections.c index fc738d5cb5..5224ab784f 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -796,8 +796,33 @@ nmc_active_connection_state_to_color (NMActiveConnectionState state, NMMetaTermC *color = NM_META_TERM_COLOR_RED; } +/* Essentially a version of nm_setting_connection_get_connection_type() that + * prefers an alias instead of the settings name when in pretty print mode. + * That is so that we print "wifi" instead of "802-11-wireless" in "nmcli c". */ +static const char * +connection_type_pretty (const char *type, NMCPrintOutput print_output) +{ + const NMMetaSettingInfoEditor *editor; + int i; + + if (print_output == NMC_PRINT_TERSE) + return type; + + for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) { + editor = &nm_meta_setting_infos_editor[i]; + if (strcmp (type, editor->general->setting_name) == 0) { + if (editor->alias) + return editor->alias; + break; + } + } + + return type; +} + static void -fill_output_connection (NMConnection *connection, NMClient *client, GPtrArray *output_data, gboolean active_only) +fill_output_connection (NMConnection *connection, NMClient *client, NMCPrintOutput print_output, + GPtrArray *output_data, gboolean active_only) { NMSettingConnection *s_con; guint64 timestamp; @@ -845,7 +870,7 @@ fill_output_connection (NMConnection *connection, NMClient *client, GPtrArray *o set_val_strc (arr, 0, nm_setting_connection_get_id (s_con)); set_val_strc (arr, 1, nm_setting_connection_get_uuid (s_con)); - set_val_strc (arr, 2, nm_setting_connection_get_connection_type (s_con)); + set_val_strc (arr, 2, connection_type_pretty (nm_setting_connection_get_connection_type (s_con), print_output)); set_val_str (arr, 3, timestamp_str); set_val_str (arr, 4, timestamp ? timestamp_real_str : g_strdup (_("never"))); set_val_strc (arr, 5, nm_setting_connection_get_autoconnect (s_con) ? _("yes") : _("no")); @@ -862,7 +887,7 @@ fill_output_connection (NMConnection *connection, NMClient *client, GPtrArray *o } static void -fill_output_connection_for_invisible (NMActiveConnection *ac, GPtrArray *output_data) +fill_output_connection_for_invisible (NMActiveConnection *ac, NMCPrintOutput print_output, GPtrArray *output_data) { NmcOutputField *arr; const char *ac_path = NULL; @@ -878,7 +903,7 @@ fill_output_connection_for_invisible (NMActiveConnection *ac, GPtrArray *output_ set_val_str (arr, 0, name); set_val_strc (arr, 1, nm_active_connection_get_uuid (ac)); - set_val_strc (arr, 2, nm_active_connection_get_connection_type (ac)); + set_val_strc (arr, 2, connection_type_pretty (nm_active_connection_get_connection_type (ac), print_output)); set_val_strc (arr, 3, NULL); set_val_strc (arr, 4, NULL); set_val_strc (arr, 5, NULL); @@ -1696,14 +1721,14 @@ do_connections_show (NmCli *nmc, int argc, char **argv) * (e.g. private connections of a different user). Show them as well. */ invisibles = get_invisible_active_connections (nmc); for (i = 0; i < invisibles->len; i++) - fill_output_connection_for_invisible (invisibles->pdata[i], out.output_data); + fill_output_connection_for_invisible (invisibles->pdata[i], nmc->nmc_config.print_output, out.output_data); g_ptr_array_free (invisibles, TRUE); /* Sort the connections and fill the output data */ connections = nm_client_get_connections (nmc->client); sorted_cons = sort_connections (connections, nmc, order); for (i = 0; i < sorted_cons->len; i++) - fill_output_connection (sorted_cons->pdata[i], nmc->client, out.output_data, active_only); + fill_output_connection (sorted_cons->pdata[i], nmc->client, nmc->nmc_config.print_output, out.output_data, active_only); g_ptr_array_free (sorted_cons, TRUE); print_data_prepare_width (out.output_data); diff --git a/clients/cli/general.c b/clients/cli/general.c index 84c853aef0..7fa982fd2d 100644 --- a/clients/cli/general.c +++ b/clients/cli/general.c @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2015 Red Hat, Inc. + * Copyright 2010 - 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -1296,6 +1296,9 @@ do_overview (NmCli *nmc, int argc, char **argv) /* Register polkit agent */ nmc_start_polkit_agent_start_try (nmc); + /* Optionally start paging the output. */ + nmc_terminal_spawn_pager (&nmc->nmc_config); + /* The VPN connections don't have devices (yet?). */ p = nm_client_get_active_connections (nmc->client); for (i = 0; i < p->len; i++) { diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c index c712fdec21..70d78db6f0 100644 --- a/clients/cli/nmcli.c +++ b/clients/cli/nmcli.c @@ -16,7 +16,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2015 Red Hat, Inc. + * Copyright 2010 - 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -93,7 +93,9 @@ complete_field (GHashTable *h, const NmcMetaGenericInfo *const*field) static void complete_one (gpointer key, gpointer value, gpointer user_data) { - const char *prefix = user_data; + const char **option_with_value = user_data; + const char *option = option_with_value[0]; + const char *prefix = option_with_value[1]; const char *name = key; const char *last; @@ -104,16 +106,23 @@ complete_one (gpointer key, gpointer value, gpointer user_data) last = prefix; if ((!*last && !strchr (name, '.')) || matches (last, name)) { + if (option != prefix) { + /* value prefix was not a standalone argument, + * it was part of --option=<value> argument. + * Repeat the part leading to "=". */ + g_print ("%s=", option); + } g_print ("%.*s%s%s\n", (int)(last-prefix), prefix, name, strcmp (last, name) == 0 ? "," : ""); } } static void -complete_fields (const char *prefix) +complete_fields (const char *option, const char *prefix) { guint i; GHashTable *h; + const char *option_with_value[2] = { option, prefix }; h = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); @@ -144,10 +153,30 @@ complete_fields (const char *prefix) for (i = 0; i < _NM_META_SETTING_TYPE_NUM; i++) complete_field_setting (h, i); - g_hash_table_foreach (h, complete_one, (gpointer) prefix); + g_hash_table_foreach (h, complete_one, (gpointer) &option_with_value[0]); g_hash_table_destroy (h); } +static void +complete_option_with_value (const char *option, const char *prefix, ...) +{ + va_list args; + const char *candidate; + + va_start (args, prefix); + while ((candidate = va_arg (args, const char *))) { + if (!*prefix || matches (prefix, candidate)) { + if (option != prefix) { + /* value prefix was not a standalone argument, + * it was part of --option=<value> argument. + * Repeat the part leading to "=". */ + g_print ("%s=", option); + } + g_print ("%s\n", candidate); + } + } + va_end (args); +} static void usage (void) @@ -191,6 +220,57 @@ static const NMCCommand nmcli_cmds[] = { }; static gboolean +matches_arg (NmCli *nmc, int *argc, char ***argv, const char *pattern, char **arg) +{ + char *opt = *argv[0]; + + if (nmc->return_value != NMC_RESULT_SUCCESS) { + /* Don't process further matches if there has been an error. */ + return FALSE; + } + + if (opt[1] == '-') { + /* We know one '-' was already seen by the caller. + * Skip it if there's a second one*/ + opt++; + } + + if (arg) { + /* If there's a "=" separator, replace it with NUL so that matches() + * works and consider the part after it to be the arguemnt's value. */ + *arg = strchr (opt, '='); + if (*arg) { + **arg = '\0'; + (*arg)++; + } + } + + if (!matches (opt, pattern)) { + if (arg && *arg) { + /* Back off the replacement of "=". */ + (*arg)--; + **arg = '='; + } + return FALSE; + } + + if (arg && !*arg) { + /* We need a value, but the option didn't contain a "=<value>" part. + * Proceed to the next argument. */ + (*argc)--; + (*argv)++; + if (!*argc) { + g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + return FALSE; + } + *arg = *argv[0]; + } + + return TRUE; +} + +static gboolean process_command_line (NmCli *nmc, int argc, char **argv) { char *base; @@ -209,26 +289,24 @@ process_command_line (NmCli *nmc, int argc, char **argv) /* parse options */ while (argc) { - char *opt = argv[0]; - if (opt[0] != '-') + char *value; + + if (argv[0][0] != '-') break; if (argc == 1 && nmc->complete) { - nmc_complete_strings (opt, "--terse", "--pretty", "--mode", "--colors", "--escape", + nmc_complete_strings (argv[0], "--terse", "--pretty", "--mode", "--colors", "--escape", "--fields", "--nocheck", "--get-values", "--wait", "--version", "--help", NULL); } - if (opt[1] == '-') { - opt++; + if (argv[0][1] == '-' && argv[0][2] == '\0') { /* '--' ends options */ - if (opt[1] == '\0') { - next_arg (nmc, &argc, &argv, NULL); - break; - } + next_arg (nmc, &argc, &argv, NULL); + break; } - if (matches (opt, "-terse")) { + if (matches_arg (nmc, &argc, &argv, "-terse", NULL)) { if (nmc->nmc_config.print_output == NMC_PRINT_TERSE) { g_string_printf (nmc->return_text, _("Error: Option '--terse' is specified the second time.")); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; @@ -241,7 +319,7 @@ process_command_line (NmCli *nmc, int argc, char **argv) } else nmc->nmc_config_mutable.print_output = NMC_PRINT_TERSE; - } else if (matches (opt, "-pretty")) { + } else if (matches_arg (nmc, &argc, &argv, "-pretty", NULL)) { if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY) { g_string_printf (nmc->return_text, _("Error: Option '--pretty' is specified the second time.")); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; @@ -254,126 +332,86 @@ process_command_line (NmCli *nmc, int argc, char **argv) } else nmc->nmc_config_mutable.print_output = NMC_PRINT_PRETTY; - } else if (matches (opt, "-mode")) { + } else if (matches_arg (nmc, &argc, &argv, "-mode", &value)) { nmc->mode_specified = TRUE; - argc--; - argv++; - if (!argc) { - g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - return FALSE; - } if (argc == 1 && nmc->complete) - nmc_complete_strings (argv[0], "tabular", "multiline", NULL); - if (matches (argv[0], "tabular")) + complete_option_with_value (argv[0], value, "tabular", "multiline", NULL); + if (matches (value, "tabular")) nmc->nmc_config_mutable.multiline_output = FALSE; - else if (matches (argv[0], "multiline")) + else if (matches (value, "multiline")) nmc->nmc_config_mutable.multiline_output = TRUE; else { - g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - return FALSE; - } - } else if (matches (opt, "-colors")) { - argc--; - argv++; - if (!argc) { - g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt); + g_string_printf (nmc->return_text, _("Error: '%s' is not a valid argument for '%s' option."), value, argv[0]); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return FALSE; } + } else if (matches_arg (nmc, &argc, &argv, "-colors", &value)) { if (argc == 1 && nmc->complete) - nmc_complete_strings (argv[0], "yes", "no", "auto", NULL); - if (matches (argv[0], "auto")) + complete_option_with_value (argv[0], value, "yes", "no", "auto", NULL); + if (matches (value, "auto")) nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_AUTO; - else if (matches (argv[0], "yes")) + else if (matches (value, "yes")) nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_YES; - else if (matches (argv[0], "no")) + else if (matches (value, "no")) nmc->nmc_config_mutable.use_colors = NMC_USE_COLOR_NO; else { - g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - return FALSE; - } - } else if (matches (opt, "-escape")) { - argc--; - argv++; - if (!argc) { - g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt); + g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), value, argv[0]); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return FALSE; } + } else if (matches_arg (nmc, &argc, &argv, "-escape", &value)) { if (argc == 1 && nmc->complete) - nmc_complete_strings (argv[0], "yes", "no", NULL); - if (matches (argv[0], "yes")) + complete_option_with_value (argv[0], value, "yes", "no", NULL); + if (matches (value, "yes")) nmc->nmc_config_mutable.escape_values = TRUE; - else if (matches (argv[0], "no")) + else if (matches (value, "no")) nmc->nmc_config_mutable.escape_values = FALSE; else { - g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), argv[0], opt); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - return FALSE; - } - } else if (matches (opt, "-fields")) { - argc--; - argv++; - if (!argc) { - g_string_printf (nmc->return_text, _("Error: fields for '%s' options are missing."), opt); + g_string_printf (nmc->return_text, _("Error: '%s' is not valid argument for '%s' option."), value, argv[0]); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return FALSE; } + } else if (matches_arg (nmc, &argc, &argv, "-fields", &value)) { if (argc == 1 && nmc->complete) - complete_fields (argv[0]); - nmc->required_fields = g_strdup (argv[0]); - } else if (matches (opt, "-get-values")) { - argc--; - argv++; - if (!argc) { - g_string_printf (nmc->return_text, _("Error: fields for '%s' options are missing."), opt); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - return FALSE; - } + complete_fields (argv[0], value); + nmc->required_fields = g_strdup (value); + } else if (matches_arg (nmc, &argc, &argv, "-get-values", &value)) { if (argc == 1 && nmc->complete) - complete_fields (argv[0]); - nmc->required_fields = g_strdup (argv[0]); + complete_fields (argv[0], value); + nmc->required_fields = g_strdup (value); nmc->nmc_config_mutable.print_output = NMC_PRINT_TERSE; /* We want fixed tabular mode here, but just set the mode specified and rely on the initialization * in nmc_init: in this way we allow use of "-m multiline" to swap the output mode also if placed * before the "-g <field>" option (-g may be still more practical and easy to remember than -t -f). */ nmc->mode_specified = TRUE; - } else if (matches (opt, "-nocheck")) { + } else if (matches_arg (nmc, &argc, &argv, "-nocheck", NULL)) { /* ignore for backward compatibility */ - } else if (matches (opt, "-wait")) { + } else if (matches_arg (nmc, &argc, &argv, "-wait", &value)) { unsigned long timeout; - argc--; - argv++; - if (!argc) { - g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; - return FALSE; - } - if (!nmc_string_to_uint (argv[0], TRUE, 0, G_MAXINT, &timeout)) { - g_string_printf (nmc->return_text, _("Error: '%s' is not a valid timeout for '%s' option."), - argv[0], opt); + if (!nmc_string_to_uint (value, TRUE, 0, G_MAXINT, &timeout)) { + g_string_printf (nmc->return_text, _("Error: '%s' is not a valid timeout."), value); nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; return FALSE; } nmc->timeout = (int) timeout; - } else if (matches (opt, "-version")) { + } else if (matches_arg (nmc, &argc, &argv, "-version", NULL)) { if (!nmc->complete) g_print (_("nmcli tool, version %s\n"), NMCLI_VERSION); return NMC_RESULT_SUCCESS; - } else if (matches (opt, "-help")) { + } else if (matches_arg (nmc, &argc, &argv, "-help", NULL)) { if (!nmc->complete) usage (); return NMC_RESULT_SUCCESS; } else { - g_string_printf (nmc->return_text, _("Error: Option '%s' is unknown, try 'nmcli -help'."), opt); - nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + if (nmc->return_value == NMC_RESULT_SUCCESS) { + g_string_printf (nmc->return_text, _("Error: Option '%s' is unknown, try 'nmcli -help'."), argv[0]); + nmc->return_value = NMC_RESULT_ERROR_USER_INPUT; + } return FALSE; } + next_arg (nmc, &argc, &argv, NULL); } @@ -547,7 +585,9 @@ nmc_init (NmCli *nmc) static void nmc_cleanup (NmCli *nmc) { - if (nmc->client) g_object_unref (nmc->client); + pid_t ret; + + g_clear_object (&nmc->client); g_string_free (nmc->return_text, TRUE); @@ -561,6 +601,15 @@ nmc_cleanup (NmCli *nmc) g_free (nmc->required_fields); + if (nmc->pager_pid > 0) { + fclose (stdout); + fclose (stderr); + do { + ret = waitpid (nmc->pager_pid, NULL, 0); + } while (ret == -1 && errno == EINTR); + nmc->pager_pid = 0; + } + nmc_polkit_agent_fini (nmc); } diff --git a/clients/cli/nmcli.h b/clients/cli/nmcli.h index 71ddb05596..874bca214b 100644 --- a/clients/cli/nmcli.h +++ b/clients/cli/nmcli.h @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2015 Red Hat, Inc. + * Copyright 2010 - 2017 Red Hat, Inc. */ #ifndef NMC_NMCLI_H @@ -129,6 +129,7 @@ typedef struct _NmCli { NMCResultCode return_value; /* Return code of nmcli */ GString *return_text; /* Reason text */ + pid_t pager_pid; /* PID of a pager, if one was spawned */ int timeout; /* Operation timeout */ diff --git a/clients/cli/utils.c b/clients/cli/utils.c index f48d8639b9..117a33d62e 100644 --- a/clients/cli/utils.c +++ b/clients/cli/utils.c @@ -14,7 +14,8 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2015 Red Hat, Inc. + * Copyright 2010 Lennart Poettering + * Copyright 2010 - 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -28,6 +29,7 @@ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <sys/prctl.h> #include "nm-client-utils.h" #include "nm-meta-setting-access.h" @@ -122,7 +124,7 @@ use_colors (NmcColorOption color_option) if (G_UNLIKELY (cached == NMC_USE_COLOR_AUTO)) { if ( g_strcmp0 (g_getenv ("TERM"), "dumb") == 0 - || !isatty (fileno (stdout))) + || !isatty (STDOUT_FILENO)) cached = NMC_USE_COLOR_NO; else cached = NMC_USE_COLOR_YES; @@ -1450,6 +1452,109 @@ nmc_print (const NmcConfig *nmc_config, /*****************************************************************************/ +static void +pager_fallback (void) +{ + char buf[64]; + int rb; + + do { + rb = read (STDIN_FILENO, buf, sizeof (buf)); + if (rb == -1) { + if (errno == EINTR) { + continue; + } else { + g_printerr (_("Error reading nmcli output: %s\n"), strerror (errno)); + _exit(EXIT_FAILURE); + } + } + if (write (STDOUT_FILENO, buf, rb) == -1) { + g_printerr (_("Error writing nmcli output: %s\n"), strerror (errno)); + _exit(EXIT_FAILURE); + } + } while (rb > 0); + + _exit(EXIT_SUCCESS); +} + +void +nmc_terminal_spawn_pager (const NmcConfig *nmc_config) +{ + const char *pager = getenv ("PAGER"); + pid_t parent_pid; + int fd[2]; + + if ( nm_cli.pager_pid > 0 + || nmc_config->print_output == NMC_PRINT_TERSE + || !use_colors (nmc_config->use_colors) + || g_strcmp0 (pager, "") == 0) + return; + + if (pipe (fd) == -1) { + g_printerr (_("Failed to create pager pipe: %s\n"), strerror (errno)); + return; + } + + parent_pid = getpid (); + + nm_cli.pager_pid = fork (); + if (nm_cli.pager_pid == -1) { + g_printerr (_("Failed to fork pager: %s\n"), strerror (errno)); + close (fd[0]); + close (fd[1]); + return; + } + + /* In the child start the pager */ + if (nm_cli.pager_pid == 0) { + dup2 (fd[0], STDIN_FILENO); + close (fd[0]); + close (fd[1]); + + setenv ("LESS", "FRSXMK", 1); + setenv ("LESSCHARSET", "utf-8", 1); + + /* Make sure the pager goes away when the parent dies */ + if (prctl (PR_SET_PDEATHSIG, SIGTERM) < 0) + _exit (EXIT_FAILURE); + + /* Check whether our parent died before we were able + * to set the death signal */ + if (getppid () != parent_pid) + _exit (EXIT_SUCCESS); + + if (pager) { + execlp (pager, pager, NULL); + execl ("/bin/sh", "sh", "-c", pager, NULL); + } + + /* Debian's alternatives command for pagers is + * called 'pager'. Note that we do not call + * sensible-pagers here, since that is just a + * shell script that implements a logic that + * is similar to this one anyway, but is + * Debian-specific. */ + execlp ("pager", "pager", NULL); + + execlp ("less", "less", NULL); + execlp ("more", "more", NULL); + + pager_fallback (); + /* not reached */ + } + + /* Return in the parent */ + if (dup2 (fd[1], STDOUT_FILENO) < 0) + g_printerr (_("Failed to duplicate pager pipe: %s\n"), strerror (errno)); + if (dup2 (fd[1], STDERR_FILENO) < 0) + g_printerr (_("Failed to duplicate pager pipe: %s\n"), strerror (errno)); + + close (fd[0]); + close (fd[1]); +} + +/*****************************************************************************/ + static const char * get_value_to_print (NmcColorOption color_option, const NmcOutputField *field, @@ -1514,6 +1619,9 @@ print_required_fields (const NmcConfig *nmc_config, gboolean field_names = of_flags & NMC_OF_FLAG_FIELD_NAMES; gboolean section_prefix = of_flags & NMC_OF_FLAG_SECTION_PREFIX; + /* Optionally start paging the output. */ + nmc_terminal_spawn_pager (nmc_config); + /* --- Main header --- */ if ((main_header_add || main_header_only) && pretty) { gs_free char *line = NULL; diff --git a/clients/cli/utils.h b/clients/cli/utils.h index 32a638af46..1724d4391e 100644 --- a/clients/cli/utils.h +++ b/clients/cli/utils.h @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2010 - 2015 Red Hat, Inc. + * Copyright 2010 - 2017 Red Hat, Inc. */ #ifndef NMC_UTILS_H @@ -40,6 +40,8 @@ gboolean nmc_parse_args (nmc_arg_t *arg_arr, gboolean last, int *argc, char ***a char *ssid_to_hex (const char *str, gsize len); void nmc_terminal_erase_line (void); void nmc_terminal_show_progress (const char *str); +void nmc_terminal_spawn_pager (const NmcConfig *nmc_config); +gboolean nmc_term_use_colors (NmcColorOption color_option); const char *nmc_term_color_sequence (NMMetaTermColor color); const char *nmc_term_format_sequence (NMMetaTermFormat format); NMMetaTermColor nmc_term_color_parse_string (const char *str, GError **error); |