diff options
| author | Michael Biebl <biebl@debian.org> | 2018-04-23 18:00:21 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2018-04-23 18:00:21 +0200 |
| commit | f60117b41d5433be1b4a96d82cd11d0c3dce9b63 (patch) | |
| tree | 2dd55c4ab0fdcbe9cddb26adb4a554b1a45c73c8 /clients/cli | |
| parent | 7e9ff09fcb2366b383b7ebbec80d2f6fff117290 (diff) | |
New upstream version 1.11.3 upstream/1.11.3
Diffstat (limited to 'clients/cli')
| -rw-r--r-- | clients/cli/agent.c | 2 | ||||
| -rw-r--r-- | clients/cli/common.c | 129 | ||||
| -rw-r--r-- | clients/cli/connections.c | 238 | ||||
| -rw-r--r-- | clients/cli/devices.c | 7 | ||||
| -rw-r--r-- | clients/cli/general.c | 3 | ||||
| -rw-r--r-- | clients/cli/meson.build | 48 | ||||
| -rw-r--r-- | clients/cli/nmcli.c | 20 | ||||
| -rw-r--r-- | clients/cli/nmcli.h | 12 | ||||
| -rw-r--r-- | clients/cli/polkit-agent.c | 73 | ||||
| -rw-r--r-- | clients/cli/settings.c | 9 | ||||
| -rw-r--r-- | clients/cli/utils.c | 27 | ||||
| -rw-r--r-- | clients/cli/utils.h | 2 |
12 files changed, 337 insertions, 233 deletions
diff --git a/clients/cli/agent.c b/clients/cli/agent.c index 488b16f4..46725c94 100644 --- a/clients/cli/agent.c +++ b/clients/cli/agent.c @@ -104,7 +104,7 @@ get_secrets_from_user (const char *request_id, rl_startup_hook = set_deftext; pre_input_deftext = g_strdup (secret->value); } - pwd = nmc_readline ("%s (%s): ", secret->name, secret->prop_name); + pwd = nmc_readline ("%s (%s): ", secret->pretty_name, secret->entry_id); /* No password provided, cancel the secrets. */ if (!pwd) diff --git a/clients/cli/common.c b/clients/cli/common.c index 0f5aea57..81a3183d 100644 --- a/clients/cli/common.c +++ b/clients/cli/common.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 2012 - 2014 Red Hat, Inc. + * Copyright 2012 - 2017 Red Hat, Inc. */ #include "nm-default.h" @@ -26,12 +26,10 @@ #include <stdio.h> #include <stdlib.h> #include <errno.h> -#include <termios.h> #include <sys/ioctl.h> #include <readline/readline.h> #include <readline/history.h> -#include "nm-utils/nm-hash-utils.h" #include "nm-vpn-helpers.h" #include "nm-client-utils.h" @@ -109,6 +107,7 @@ _metagen_ip4_config_get_fcn (const NMMetaEnvironment *environment, NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, + gboolean *out_is_default, gpointer *out_to_free) { NMIPConfig *cfg4 = target; @@ -116,10 +115,12 @@ _metagen_ip4_config_get_fcn (const NMMetaEnvironment *environment, char **arr; const char *const*arrc; guint i = 0; + const char *str; nm_assert (info->info_type < _NMC_GENERIC_INFO_TYPE_IP4_CONFIG_NUM); NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL); + NM_SET_OUT (out_is_default, TRUE); switch (info->info_type) { case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ADDRESS: @@ -140,7 +141,9 @@ _metagen_ip4_config_get_fcn (const NMMetaEnvironment *environment, arr = NULL; goto arr_out; case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_GATEWAY: - return nm_ip_config_get_gateway (cfg4); + str = nm_ip_config_get_gateway (cfg4); + NM_SET_OUT (out_is_default, !str); + return str; case NMC_GENERIC_INFO_TYPE_IP4_CONFIG_ROUTE: if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV)) return NULL; @@ -168,10 +171,12 @@ _metagen_ip4_config_get_fcn (const NMMetaEnvironment *environment, g_return_val_if_reached (NULL); arrc_out: + NM_SET_OUT (out_is_default, !arrc || !arrc[0]); *out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV; return arrc; arr_out: + NM_SET_OUT (out_is_default, !arr || !arr[0]); *out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV; *out_to_free = arr; return arr; @@ -185,6 +190,7 @@ _metagen_ip6_config_get_fcn (const NMMetaEnvironment *environment, NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, + gboolean *out_is_default, gpointer *out_to_free) { NMIPConfig *cfg6 = target; @@ -192,10 +198,12 @@ _metagen_ip6_config_get_fcn (const NMMetaEnvironment *environment, char **arr; const char *const*arrc; guint i = 0; + const char *str; nm_assert (info->info_type < _NMC_GENERIC_INFO_TYPE_IP6_CONFIG_NUM); NMC_HANDLE_TERMFORMAT (NM_META_TERM_COLOR_NORMAL); + NM_SET_OUT (out_is_default, TRUE); switch (info->info_type) { case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ADDRESS: @@ -216,7 +224,9 @@ _metagen_ip6_config_get_fcn (const NMMetaEnvironment *environment, arr = NULL; goto arr_out; case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_GATEWAY: - return nm_ip_config_get_gateway (cfg6); + str = nm_ip_config_get_gateway (cfg6); + NM_SET_OUT (out_is_default, !str); + return str; case NMC_GENERIC_INFO_TYPE_IP6_CONFIG_ROUTE: if (!NM_FLAGS_HAS (get_flags, NM_META_ACCESSOR_GET_FLAGS_ACCEPT_STRV)) return NULL; @@ -239,10 +249,12 @@ _metagen_ip6_config_get_fcn (const NMMetaEnvironment *environment, g_return_val_if_reached (NULL); arrc_out: + NM_SET_OUT (out_is_default, !arrc || !arrc[0]); *out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV; return arrc; arr_out: + NM_SET_OUT (out_is_default, !arr || !arr[0]); *out_flags |= NM_META_ACCESSOR_GET_OUT_FLAGS_STRV; *out_to_free = arr; return arr; @@ -532,10 +544,10 @@ vpn_openconnect_get_secrets (NMConnection *connection, GPtrArray *secrets) { GError *error = NULL; NMSettingVpn *s_vpn; - const char *vpn_type, *gw, *port; - char *cookie = NULL; - char *gateway = NULL; - char *gwcert = NULL; + const char *gw, *port; + gs_free char *cookie = NULL; + gs_free char *gateway = NULL; + gs_free char *gwcert = NULL; int status = 0; int i; gboolean ret; @@ -547,8 +559,7 @@ vpn_openconnect_get_secrets (NMConnection *connection, GPtrArray *secrets) return FALSE; s_vpn = nm_connection_get_setting_vpn (connection); - vpn_type = nm_setting_vpn_get_service_type (s_vpn); - if (g_strcmp0 (vpn_type, NM_DBUS_INTERFACE ".openconnect")) + if (!nm_streq0 (nm_setting_vpn_get_service_type (s_vpn), NM_SECRET_AGENT_VPN_TYPE_OPENCONNECT)) return FALSE; /* Get gateway and port */ @@ -571,34 +582,31 @@ vpn_openconnect_get_secrets (NMConnection *connection, GPtrArray *secrets) /* Append port to the host value */ if (gateway && port) { - char *tmp = gateway; - gateway = g_strdup_printf ("%s%s", gateway, port); - g_free (tmp); + gs_free char *tmp = gateway; + + gateway = g_strdup_printf ("%s%s", tmp, port); } /* Fill secrets to the array */ for (i = 0; i < secrets->len; i++) { NMSecretAgentSimpleSecret *secret = secrets->pdata[i]; - if (!g_strcmp0 (secret->vpn_type, vpn_type)) { - if (!g_strcmp0 (secret->vpn_property, "cookie")) { - g_free (secret->value); - secret->value = cookie; - cookie = NULL; - } else if (!g_strcmp0 (secret->vpn_property, "gateway")) { - g_free (secret->value); - secret->value = gateway; - gateway = NULL; - } else if (!g_strcmp0 (secret->vpn_property, "gwcert")) { - g_free (secret->value); - secret->value = gwcert; - gwcert = NULL; - } + if (secret->secret_type != NM_SECRET_AGENT_SECRET_TYPE_VPN_SECRET) + continue; + if (!nm_streq0 (secret->vpn_type, NM_SECRET_AGENT_VPN_TYPE_OPENCONNECT)) + continue; + + if (nm_streq0 (secret->entry_id, NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET "cookie")) { + g_free (secret->value); + secret->value = g_steal_pointer (&cookie); + } else if (nm_streq0 (secret->entry_id, NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET "gateway")) { + g_free (secret->value); + secret->value = g_steal_pointer (&gateway); + } else if (nm_streq0 (secret->entry_id, NM_SECRET_AGENT_ENTRY_ID_PREFX_VPN_SECRET "gwcert")) { + g_free (secret->value); + secret->value = g_steal_pointer (&gwcert); } } - g_free (cookie); - g_free (gateway); - g_free (gwcert); return TRUE; } @@ -625,7 +633,7 @@ get_secrets_from_user (const char *request_id, /* First try to find the password in provided passwords file, * then ask user. */ - if (pwds_hash && (pwd = g_hash_table_lookup (pwds_hash, secret->prop_name))) { + if (pwds_hash && (pwd = g_hash_table_lookup (pwds_hash, secret->entry_id))) { pwd = g_strdup (pwd); } else { if (ask) { @@ -641,8 +649,10 @@ get_secrets_from_user (const char *request_id, } if (msg) g_print ("%s\n", msg); - pwd = nmc_readline_echo (secret->password ? echo_on : TRUE, - "%s (%s): ", secret->name, secret->prop_name); + pwd = nmc_readline_echo (secret->is_secret + ? echo_on + : TRUE, + "%s (%s): ", secret->pretty_name, secret->entry_id); if (!pwd) pwd = g_strdup (""); } else { @@ -650,7 +660,7 @@ get_secrets_from_user (const char *request_id, g_print ("%s\n", msg); g_printerr (_("Warning: password for '%s' not given in 'passwd-file' " "and nmcli cannot ask without '--ask' option.\n"), - secret->prop_name); + secret->entry_id); } } /* No password provided, cancel the secrets. */ @@ -883,6 +893,31 @@ nmc_readline (const char *prompt_fmt, ...) return str; } +static void +nmc_secret_redisplay (void) +{ + int save_point = rl_point; + int save_end = rl_end; + char *save_line_buffer = rl_line_buffer; + const char *subst = nmc_password_subst_char (); + int subst_len = strlen (subst); + int i; + + rl_point = g_utf8_strlen (save_line_buffer, save_point) * subst_len; + rl_end = g_utf8_strlen (rl_line_buffer, -1) * subst_len; + rl_line_buffer = g_slice_alloc (rl_end + 1); + + for (i = 0; i + subst_len <= rl_end; i += subst_len) + memcpy (&rl_line_buffer[i], subst, subst_len); + rl_line_buffer[i] = '\0'; + + rl_redisplay (); + g_slice_free1 (rl_end + 1, rl_line_buffer); + rl_line_buffer = save_line_buffer; + rl_end = save_end; + rl_point = save_point; +} + /** * nmc_readline_echo: * @@ -894,29 +929,28 @@ nmc_readline_echo (gboolean echo_on, const char *prompt_fmt, ...) { va_list args; char *prompt, *str; - struct termios termios_orig, termios_new; + HISTORY_STATE *saved_history; + HISTORY_STATE passwd_history = { 0, }; va_start (args, prompt_fmt); prompt = g_strdup_vprintf (prompt_fmt, args); va_end (args); - /* Disable echoing characters */ + /* Hide the actual password */ if (!echo_on) { - tcgetattr (STDIN_FILENO, &termios_orig); - termios_new = termios_orig; - termios_new.c_lflag &= ~(ECHO); - tcsetattr (STDIN_FILENO, TCSADRAIN, &termios_new); + saved_history = history_get_history_state (); + history_set_history_state (&passwd_history); + rl_redisplay_function = nmc_secret_redisplay; } str = nmc_readline_helper (prompt); g_free (prompt); - /* Restore original terminal settings */ + /* Restore the non-hiding behavior */ if (!echo_on) { - tcsetattr (STDIN_FILENO, TCSADRAIN, &termios_orig); - /* New line - setting ECHONL | ICANON did not help */ - fprintf (stdout, "\n"); + rl_redisplay_function = rl_redisplay; + history_set_history_state (saved_history); } return str; @@ -1215,9 +1249,8 @@ nmc_do_cmd (NmCli *nmc, const NMCCommand cmds[], const char *cmd, int argc, char /* A valid command was specified. */ if (c->usage && argc == 2 && nmc->complete) nmc_complete_help (*(argv+1)); - if (c->usage && nmc_arg_is_help (*(argv+1))) { - if (!nmc->complete) - c->usage (); + if (!nmc->complete && c->usage && nmc_arg_is_help (*(argv+1))) { + c->usage (); g_simple_async_result_complete_in_idle (simple); g_object_unref (simple); } else { diff --git a/clients/cli/connections.c b/clients/cli/connections.c index e0f55c53..705d3c25 100644 --- a/clients/cli/connections.c +++ b/clients/cli/connections.c @@ -31,8 +31,6 @@ #include <readline/readline.h> #include <readline/history.h> -#include "nm-utils/nm-hash-utils.h" - #include "nm-client-utils.h" #include "nm-vpn-helpers.h" #include "nm-meta-setting-access.h" @@ -505,12 +503,8 @@ usage_connection_export (void) static void quit (void) { - if (progress_id) { - g_source_remove (progress_id); - progress_id = 0; + if (nm_clear_g_source (&progress_id)) nmc_terminal_erase_line (); - } - g_main_loop_quit (loop); } @@ -1128,7 +1122,6 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) const char *fields_str = NULL; const NMMetaAbstractInfo *const*tmpl; NmcOutputField *arr; - size_t tmpl_len; const char *base_hdr = _("Activate connection details"); gboolean was_output = FALSE; @@ -1182,7 +1175,6 @@ nmc_active_connection_details (NMActiveConnection *acon, NmCli *nmc) /* Add field names */ tmpl = (const NMMetaAbstractInfo *const*) nmc_fields_con_active_details_general; - tmpl_len = sizeof (nmc_fields_con_active_details_general); out_indices = parse_output_fields (group_fld, tmpl, FALSE, NULL, NULL); arr = nmc_dup_fields_array (tmpl, NMC_OF_FLAG_FIELD_NAMES); @@ -1589,18 +1581,18 @@ get_invisible_active_connections (NmCli *nmc) static GArray * parse_preferred_connection_order (const char *order, GError **error) { - char **strv, **iter; + gs_free const char **strv = NULL; + const char *const*iter; const char *str; GArray *order_arr; NmcSortOrder val; gboolean inverse, unique; int i; - strv = nmc_strsplit_set (order, ":", -1); - if (!strv || !*strv) { + strv = nm_utils_strsplit_set (order, ":"); + if (!strv) { g_set_error (error, NMCLI_ERROR, 0, _("incorrect string '%s' of '--order' option"), order); - g_strfreev (strv); return NULL; } @@ -1642,7 +1634,6 @@ parse_preferred_connection_order (const char *order, GError **error) g_array_append_val (order_arr, val); } - g_strfreev (strv); return order_arr; } @@ -1662,16 +1653,17 @@ get_connection (NmCli *nmc, int *argc, char ***argv, int *pos, GError **error) if (*argc == 1 && nmc->complete) nmc_complete_strings (**argv, "id", "uuid", "path", NULL); - if ( strcmp (**argv, "id") == 0 - || strcmp (**argv, "uuid") == 0 - || strcmp (**argv, "path") == 0) { - selector = **argv; - (*argc)--; - (*argv)++; - if (!*argc) { - g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, - _("%s argument is missing"), selector); - return NULL; + if (NM_IN_STRSET (**argv, "id", "uuid", "path")) { + if (*argc == 1) { + if (!nmc->complete) { + g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, + _("%s argument is missing"), selector); + return NULL; + } + } else { + selector = **argv; + (*argv)++; + (*argc)--; } } @@ -2295,48 +2287,50 @@ activate_connection_cb (GObject *client, GAsyncResult *result, gpointer user_dat static GHashTable * parse_passwords (const char *passwd_file, GError **error) { - GHashTable *pwds_hash; - char *contents = NULL; + gs_unref_hashtable GHashTable *pwds_hash = NULL; + gs_free char *contents = NULL; gsize len = 0; GError *local_err = NULL; - char **lines, **iter; + gs_free const char **strv = NULL; + const char *const*iter; char *pwd_spec, *pwd, *prop; const char *setting; pwds_hash = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, g_free); if (!passwd_file) - return pwds_hash; + return g_steal_pointer (&pwds_hash); - /* Read the passwords file */ + /* Read the passwords file */ if (!g_file_get_contents (passwd_file, &contents, &len, &local_err)) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("failed to read passwd-file '%s': %s"), passwd_file, local_err->message); g_error_free (local_err); - g_hash_table_destroy (pwds_hash); return NULL; } - lines = nmc_strsplit_set (contents, "\r\n", -1); - for (iter = lines; *iter; iter++) { - pwd = strchr (*iter, ':'); + strv = nm_utils_strsplit_set (contents, "\r\n"); + for (iter = strv; *iter; iter++) { + gs_free char *iter_s = g_strdup (*iter); + + pwd = strchr (iter_s, ':'); if (!pwd) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("missing colon in 'password' entry '%s'"), *iter); - goto failure; + return NULL; } *(pwd++) = '\0'; - prop = strchr (*iter, '.'); + prop = strchr (iter_s, '.'); if (!prop) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("missing dot in 'password' entry '%s'"), *iter); - goto failure; + return NULL; } *(prop++) = '\0'; - setting = *iter; + setting = iter_s; while (g_ascii_isspace (*setting)) setting++; /* Accept wifi-sec or wifi instead of cumbersome '802-11-wireless-security' */ @@ -2345,21 +2339,13 @@ parse_passwords (const char *passwd_file, GError **error) if (nm_setting_lookup_type (setting) == G_TYPE_INVALID) { g_set_error (error, NMCLI_ERROR, NMC_RESULT_ERROR_USER_INPUT, _("invalid setting name in 'password' entry '%s'"), setting); - goto failure; + return NULL; } pwd_spec = g_strdup_printf ("%s.%s", setting, prop); g_hash_table_insert (pwds_hash, pwd_spec, g_strdup (pwd)); } - g_strfreev (lines); - g_free (contents); - return pwds_hash; - -failure: - g_strfreev (lines); - g_free (contents); - g_hash_table_destroy (pwds_hash); - return NULL; + return g_steal_pointer (&pwds_hash); } @@ -3339,7 +3325,7 @@ _dynamic_options_set (const NMMetaAbstractInfo *abstract_info, PropertyInfFlags v, v2; if (G_UNLIKELY (!cache)) - cache = g_hash_table_new (NULL, NULL); + cache = g_hash_table_new (nm_direct_hash, NULL); if (g_hash_table_lookup_extended (cache, (gpointer) abstract_info, NULL, &p)) v = GPOINTER_TO_UINT (p); @@ -5889,50 +5875,80 @@ typedef enum { NMC_EDITOR_MAIN_CMD_QUIT, } NmcEditorMainCmd; +static void +_split_cmd (const char *cmd, char **out_arg0, const char **out_argr) +{ + gs_free char *arg0 = NULL; + const char *argr = NULL; + gsize l; + + NM_SET_OUT (out_arg0, NULL); + NM_SET_OUT (out_argr, NULL); + + if (!cmd) + return; + while (NM_IN_SET (cmd[0], ' ', '\t')) + cmd++; + if (!cmd[0]) + return; + + l = strcspn (cmd, " \t"); + arg0 = g_strndup (cmd, l); + cmd += l; + if (cmd[0]) { + while (NM_IN_SET (cmd[0], ' ', '\t')) + cmd++; + if (cmd[0]) + argr = cmd; + } + + NM_SET_OUT (out_arg0, g_steal_pointer (&arg0)); + NM_SET_OUT (out_argr, argr); +} + static NmcEditorMainCmd parse_editor_main_cmd (const char *cmd, char **cmd_arg) { NmcEditorMainCmd editor_cmd = NMC_EDITOR_MAIN_CMD_UNKNOWN; - char **vec; + gs_free char *cmd_arg0 = NULL; + const char *cmd_argr; - vec = nmc_strsplit_set (cmd, " \t", 2); - if (g_strv_length (vec) < 1) { - if (cmd_arg) - *cmd_arg = NULL; - return NMC_EDITOR_MAIN_CMD_UNKNOWN; - } + _split_cmd (cmd, &cmd_arg0, &cmd_argr); + if (!cmd_arg0) + goto fail; - if (matches (vec[0], "goto")) + if (matches (cmd_arg0, "goto")) editor_cmd = NMC_EDITOR_MAIN_CMD_GOTO; - else if (matches (vec[0], "remove")) + else if (matches (cmd_arg0, "remove")) editor_cmd = NMC_EDITOR_MAIN_CMD_REMOVE; - else if (matches (vec[0], "set")) + else if (matches (cmd_arg0, "set")) editor_cmd = NMC_EDITOR_MAIN_CMD_SET; - else if (matches (vec[0], "describe")) + else if (matches (cmd_arg0, "describe")) editor_cmd = NMC_EDITOR_MAIN_CMD_DESCRIBE; - else if (matches (vec[0], "print")) + else if (matches (cmd_arg0, "print")) editor_cmd = NMC_EDITOR_MAIN_CMD_PRINT; - else if (matches (vec[0], "verify")) + else if (matches (cmd_arg0, "verify")) editor_cmd = NMC_EDITOR_MAIN_CMD_VERIFY; - else if (matches (vec[0], "save")) + else if (matches (cmd_arg0, "save")) editor_cmd = NMC_EDITOR_MAIN_CMD_SAVE; - else if (matches (vec[0], "activate")) + else if (matches (cmd_arg0, "activate")) editor_cmd = NMC_EDITOR_MAIN_CMD_ACTIVATE; - else if (matches (vec[0], "back")) + else if (matches (cmd_arg0, "back")) editor_cmd = NMC_EDITOR_MAIN_CMD_BACK; - else if (matches (vec[0], "help") || strcmp (vec[0], "?") == 0) + else if (matches (cmd_arg0, "help") || strcmp (cmd_arg0, "?") == 0) editor_cmd = NMC_EDITOR_MAIN_CMD_HELP; - else if (matches (vec[0], "quit")) + else if (matches (cmd_arg0, "quit")) editor_cmd = NMC_EDITOR_MAIN_CMD_QUIT; - else if (matches (vec[0], "nmcli")) + else if (matches (cmd_arg0, "nmcli")) editor_cmd = NMC_EDITOR_MAIN_CMD_NMCLI; + else + goto fail; - /* set pointer to command argument */ - if (cmd_arg) - *cmd_arg = vec[1] ? g_strstrip (g_strdup (vec[1])) : NULL; - - g_strfreev (vec); + NM_SET_OUT (cmd_arg, g_strdup (cmd_argr)); return editor_cmd; +fail: + NM_SET_OUT (cmd_arg, NULL); + return NMC_EDITOR_MAIN_CMD_UNKNOWN; } static void @@ -6081,40 +6097,39 @@ static NmcEditorSubCmd parse_editor_sub_cmd (const char *cmd, char **cmd_arg) { NmcEditorSubCmd editor_cmd = NMC_EDITOR_SUB_CMD_UNKNOWN; - char **vec; + gs_free char *cmd_arg0 = NULL; + const char *cmd_argr; - vec = nmc_strsplit_set (cmd, " \t", 2); - if (g_strv_length (vec) < 1) { - if (cmd_arg) - *cmd_arg = NULL; - return NMC_EDITOR_SUB_CMD_UNKNOWN; - } + _split_cmd (cmd, &cmd_arg0, &cmd_argr); + if (!cmd_arg0) + goto fail; - if (matches (vec[0], "set")) + if (matches (cmd_arg0, "set")) editor_cmd = NMC_EDITOR_SUB_CMD_SET; - else if (matches (vec[0], "add")) + else if (matches (cmd_arg0, "add")) editor_cmd = NMC_EDITOR_SUB_CMD_ADD; - else if (matches (vec[0], "change")) + else if (matches (cmd_arg0, "change")) editor_cmd = NMC_EDITOR_SUB_CMD_CHANGE; - else if (matches (vec[0], "remove")) + else if (matches (cmd_arg0, "remove")) editor_cmd = NMC_EDITOR_SUB_CMD_REMOVE; - else if (matches (vec[0], "describe")) + else if (matches (cmd_arg0, "describe")) editor_cmd = NMC_EDITOR_SUB_CMD_DESCRIBE; - else if (matches (vec[0], "print")) + else if (matches (cmd_arg0, "print")) editor_cmd = NMC_EDITOR_SUB_CMD_PRINT; - else if (matches (vec[0], "back")) + else if (matches (cmd_arg0, "back")) editor_cmd = NMC_EDITOR_SUB_CMD_BACK; - else if (matches (vec[0], "help") || strcmp (vec[0], "?") == 0) + else if (matches (cmd_arg0, "help") || strcmp (cmd_arg0, "?") == 0) editor_cmd = NMC_EDITOR_SUB_CMD_HELP; - else if (matches (vec[0], "quit")) + else if (matches (cmd_arg0, "quit")) editor_cmd = NMC_EDITOR_SUB_CMD_QUIT; + else + goto fail; - /* set pointer to command argument */ - if (cmd_arg) - *cmd_arg = g_strdup (vec[1]); - - g_strfreev (vec); + NM_SET_OUT (cmd_arg, g_strdup (cmd_argr)); return editor_cmd; +fail: + NM_SET_OUT (cmd_arg, NULL); + return NMC_EDITOR_SUB_CMD_UNKNOWN; } static void @@ -6650,29 +6665,26 @@ property_edit_submenu (NmCli *nmc, static void split_editor_main_cmd_args (const char *str, char **setting, char **property, char **value) { - char **args, **items; + gs_free char *cmd_arg0 = NULL; + const char *cmd_argr; + const char *s; - if (!str) - return; + NM_SET_OUT (setting, NULL); + NM_SET_OUT (property, NULL); + NM_SET_OUT (value, NULL); - args = nmc_strsplit_set (str, " \t", 2); - if (args[0]) { - items = nmc_strsplit_set (args[0], ".", 2); - if (g_strv_length (items) == 2) { - if (setting) - *setting = g_strdup (items[0]); - if (property) - *property = g_strdup (items[1]); - } else { - if (property) - *property = g_strdup (items[0]); - } - g_strfreev (items); + _split_cmd (str, &cmd_arg0, &cmd_argr); + if (!cmd_arg0) + return; - if (value && args[1]) - *value = g_strstrip (g_strdup (args[1])); + NM_SET_OUT (value, g_strdup (cmd_argr)); + s = strchr (cmd_arg0, '.'); + if (s && s > cmd_arg0) { + NM_SET_OUT (setting, g_strndup (cmd_arg0, s - cmd_arg0)); + NM_SET_OUT (property, g_strdup (&s[1])); + } else { + NM_SET_OUT (property, g_steal_pointer (&cmd_arg0)); } - g_strfreev (args); } static NMSetting * @@ -6793,7 +6805,7 @@ confirm_connection_saving (NMConnection *local, NMConnection *remote) return confirmed; } -typedef struct { +typedef struct { guint level; char *main_prompt; NMSetting *curr_setting; diff --git a/clients/cli/devices.c b/clients/cli/devices.c index da969fbe..a43861fa 100644 --- a/clients/cli/devices.c +++ b/clients/cli/devices.c @@ -451,11 +451,8 @@ usage_device_lldp (void) static void quit (void) { - if (progress_id) { - g_source_remove (progress_id); + if (nm_clear_g_source (&progress_id)) nmc_terminal_erase_line (); - } - g_main_loop_quit (loop); } @@ -834,7 +831,7 @@ fill_output_access_point (gpointer data, gpointer user_data) strength_str = g_strdup_printf ("%u", strength); wpa_flags_str = ap_wpa_rsn_flags_to_string (wpa_flags); rsn_flags_str = ap_wpa_rsn_flags_to_string (rsn_flags); - sig_bars = nm_utils_wifi_strength_bars (strength); + sig_bars = nmc_wifi_strength_bars (strength); security_str = g_string_new (NULL); diff --git a/clients/cli/general.c b/clients/cli/general.c index 7ac6b22c..647ee5fc 100644 --- a/clients/cli/general.c +++ b/clients/cli/general.c @@ -175,6 +175,7 @@ _metagen_general_status_get_fcn (const NMMetaEnvironment *environment, NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, + gboolean *out_is_default, gpointer *out_to_free) { NmCli *nmc = target; @@ -282,6 +283,7 @@ _metagen_general_permissions_get_fcn (const NMMetaEnvironment *environment, NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, + gboolean *out_is_default, gpointer *out_to_free) { NMClientPermission perm = GPOINTER_TO_UINT (target); @@ -330,6 +332,7 @@ _metagen_general_logging_get_fcn (const NMMetaEnvironment *environment, NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, + gboolean *out_is_default, gpointer *out_to_free) { NmCli *nmc = environment_user_data; diff --git a/clients/cli/meson.build b/clients/cli/meson.build new file mode 100644 index 00000000..65317a0a --- /dev/null +++ b/clients/cli/meson.build @@ -0,0 +1,48 @@ +name = 'nmcli' + +# FIXME: nmcli-completion should be renamed to nmcli +install_data( + 'nmcli-completion', + install_dir: join_paths(nm_datadir, 'bash-completion', 'completions') +) + +sources = files( + 'agent.c', + 'common.c', + 'connections.c', + 'devices.c', + 'general.c', + 'nmcli.c', + 'polkit-agent.c', + 'settings.c', + 'utils.c' +) + +deps = [ + libnm_dep, + libnmc_base_dep, + libnmc_dep, + nm_core_dep, + readline_dep +] + +cflags = clients_cflags + [ + '-DG_LOG_DOMAIN="@0@"'.format(name), + '-DNMCLI_LOCALEDIR="@0@"'.format(nm_localedir) +] + +if enable_polkit_agent + sources += nm_polkit_listener + + deps += polkit_agent_dep +endif + +executable( + name, + sources, + dependencies: deps, + c_args: cflags, + link_args: ldflags_linker_script_binary, + link_depends: linker_script_binary, + install: true +) diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c index f5a66cdd..ec23ff43 100644 --- a/clients/cli/nmcli.c +++ b/clients/cli/nmcli.c @@ -36,8 +36,6 @@ #include "nm-client-utils.h" -#include "nm-utils/nm-hash-utils.h" - #include "polkit-agent.h" #include "utils.h" #include "common.h" @@ -186,6 +184,7 @@ usage (void) g_printerr (_("Usage: nmcli [OPTIONS] OBJECT { COMMAND | help }\n" "\n" "OPTIONS\n" + " -o[verview] overview mode (hide default values)\n" " -t[erse] terse output\n" " -p[retty] pretty output\n" " -m[ode] tabular|multiline output mode\n" @@ -297,9 +296,10 @@ process_command_line (NmCli *nmc, int argc, char **argv) break; if (argc == 1 && nmc->complete) { - nmc_complete_strings (argv[0], "--terse", "--pretty", "--mode", "--colors", "--escape", - "--fields", "--nocheck", "--get-values", - "--wait", "--version", "--help", NULL); + nmc_complete_strings (argv[0], "--terse", "--pretty", "--mode", "--overview", + "--colors", "--escape", + "--fields", "--nocheck", "--get-values", + "--wait", "--version", "--help", NULL); } if (argv[0][1] == '-' && argv[0][2] == '\0') { @@ -308,7 +308,9 @@ process_command_line (NmCli *nmc, int argc, char **argv) break; } - if (matches_arg (nmc, &argc, &argv, "-terse", NULL)) { + if (matches_arg (nmc, &argc, &argv, "-overview", NULL)) { + nmc->nmc_config_mutable.overview = TRUE; + } else 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; @@ -417,6 +419,10 @@ process_command_line (NmCli *nmc, int argc, char **argv) next_arg (nmc, &argc, &argv, NULL); } + /* Ignore --overview when fields are set explicitly */ + if (nmc->required_fields) + nmc->nmc_config_mutable.overview = FALSE; + /* Now run the requested command */ nmc_do_cmd (nmc, nmcli_cmds, *argv, argc, argv); @@ -629,8 +635,6 @@ main (int argc, char *argv[]) textdomain (GETTEXT_PACKAGE); #endif - nm_g_type_init (); - /* Save terminal settings */ tcgetattr (STDIN_FILENO, &termios_orig); diff --git a/clients/cli/nmcli.h b/clients/cli/nmcli.h index 874bca21..0f3d29cd 100644 --- a/clients/cli/nmcli.h +++ b/clients/cli/nmcli.h @@ -20,17 +20,10 @@ #ifndef NMC_NMCLI_H #define NMC_NMCLI_H -#include "NetworkManager.h" #include "nm-secret-agent-old.h" - #include "nm-meta-setting-desc.h" -#if WITH_POLKIT_AGENT -#include "nm-polkit-listener.h" -#else -/* polkit agent is not available; define fake NMPolkitListener */ -typedef gpointer NMPolkitListener; -#endif +struct _NMPolkitListener; typedef char *(*NmcCompEntryFunc) (const char *, int); @@ -117,6 +110,7 @@ typedef struct _NmcConfig { bool escape_values; /* Whether to escape ':' and '\' in terse tabular mode */ bool in_editor; /* Whether running the editor - nmcli con edit' */ bool show_secrets; /* Whether to display secrets (both input and output): option '--show-secrets' */ + bool overview; /* Overview mode (hide default values) */ } NmcConfig; typedef struct _NmcOutputData { @@ -135,7 +129,7 @@ typedef struct _NmCli { NMSecretAgentOld *secret_agent; /* Secret agent */ GHashTable *pwds_hash; /* Hash table with passwords in passwd-file */ - NMPolkitListener *pk_listener ; /* polkit agent listener */ + struct _NMPolkitListener *pk_listener; /* polkit agent listener */ int should_wait; /* Semaphore indicating whether nmcli should not end or not yet */ gboolean nowait_flag; /* '--nowait' option; used for passing to callbacks */ diff --git a/clients/cli/polkit-agent.c b/clients/cli/polkit-agent.c index ecd58ba5..338f0b15 100644 --- a/clients/cli/polkit-agent.c +++ b/clients/cli/polkit-agent.c @@ -19,8 +19,6 @@ #include "nm-default.h" -#if WITH_POLKIT_AGENT - #include "polkit-agent.h" #include <stdio.h> @@ -29,17 +27,18 @@ #include <unistd.h> #include "nm-polkit-listener.h" - #include "common.h" +#if WITH_POLKIT_AGENT static char * -polkit_request (const char *request, +polkit_request (NMPolkitListener *listener, + const char *request, const char *action_id, const char *message, const char *icon_name, const char *user, gboolean echo_on, - gpointer user_data) + gpointer user_data) { char *response, *tmp, *p; @@ -62,28 +61,42 @@ polkit_request (const char *request, } static void -polkit_show_info (const char *text) +polkit_show_info (NMPolkitListener *listener, + const char *text, + gpointer user_data) { g_print (_("Authentication message: %s\n"), text); } static void -polkit_show_error (const char *text) +polkit_show_error (NMPolkitListener *listener, + const char *text, + gpointer user_data) { g_print (_("Authentication error: %s\n"), text); } static void -polkit_completed (gboolean gained_authorization) +polkit_completed (NMPolkitListener *listener, + gboolean gained_authorization, + gpointer user_data) { /* We don't print anything here. The outcome will be evident from * the operation result anyway. */ } +#endif gboolean nmc_polkit_agent_init (NmCli* nmc, gboolean for_session, GError **error) { - PolkitAgentListener *listener; +#if WITH_POLKIT_AGENT + static const NMPolkitListenVtable vtable = { + .on_request = polkit_request, + .on_show_info = polkit_show_info, + .on_show_error = polkit_show_error, + .on_completed = polkit_completed, + }; + NMPolkitListener *listener; g_return_val_if_fail (error == NULL || *error == NULL, FALSE); @@ -91,24 +104,28 @@ nmc_polkit_agent_init (NmCli* nmc, gboolean for_session, GError **error) if (!listener) return FALSE; - nm_polkit_listener_set_request_callback (NM_POLKIT_LISTENER (listener), polkit_request, nmc); - nm_polkit_listener_set_show_info_callback (NM_POLKIT_LISTENER (listener), polkit_show_info); - nm_polkit_listener_set_show_error_callback (NM_POLKIT_LISTENER (listener), polkit_show_error); - nm_polkit_listener_set_completed_callback (NM_POLKIT_LISTENER (listener), polkit_completed); + nm_polkit_listener_set_vtable (listener, &vtable, nmc); - nmc->pk_listener = NM_POLKIT_LISTENER (listener); + nmc->pk_listener = listener; +#endif return TRUE; } void nmc_polkit_agent_fini (NmCli* nmc) { - g_clear_object (&nmc->pk_listener); +#if WITH_POLKIT_AGENT + if (nmc->pk_listener) { + nm_polkit_listener_set_vtable (nmc->pk_listener, NULL, NULL); + g_clear_object (&nmc->pk_listener); + } +#endif } gboolean nmc_start_polkit_agent_start_try (NmCli *nmc) { +#if WITH_POLKIT_AGENT GError *error = NULL; /* We don't register polkit agent at all when running non-interactively */ @@ -121,30 +138,6 @@ nmc_start_polkit_agent_start_try (NmCli *nmc) g_error_free (error); return FALSE; } +#endif return TRUE; } - -#else -/* polkit agent is not avalable; implement stub functions. */ - -#include "nmcli.h" -#include "polkit-agent.h" - -gboolean -nmc_polkit_agent_init (NmCli* nmc, gboolean for_session, GError **error) -{ - return TRUE; -} - -void -nmc_polkit_agent_fini (NmCli* nmc) -{ -} - -gboolean -nmc_start_polkit_agent_start_try (NmCli *nmc) -{ - return TRUE; -} - -#endif /* #if WITH_POLKIT_AGENT */ diff --git a/clients/cli/settings.c b/clients/cli/settings.c index 69275aad..5c3deead 100644 --- a/clients/cli/settings.c +++ b/clients/cli/settings.c @@ -313,16 +313,18 @@ _set_fcn_precheck_connection_secondaries (const char *value, { const GPtrArray *connections; NMConnection *con; + gs_free const char **strv0 = NULL; gs_strfreev char **strv = NULL; char **iter; - gboolean modified; + gboolean modified = FALSE; - strv = nmc_strsplit_set (value, " \t,", 0); - if (!strv) + strv0 = nm_utils_strsplit_set (value, " \t,"); + if (!strv0) return TRUE; connections = nm_client_get_connections (nm_cli.client); + strv = g_strdupv ((char **) strv0); for (iter = strv; *iter; iter++) { if (nm_utils_is_uuid (*iter)) { con = nmc_find_connection (connections, "uuid", *iter, NULL, FALSE); @@ -472,6 +474,7 @@ get_property_val (NMSetting *setting, const char *prop, NMMetaAccessorGetType ge get_type, show_secrets ? NM_META_ACCESSOR_GET_FLAGS_SHOW_SECRETS : 0, &out_flags, + NULL, (gpointer *) &to_free); nm_assert (!out_flags); return to_free ?: g_strdup (value); diff --git a/clients/cli/utils.c b/clients/cli/utils.c index f20e24ce..71fdcf30 100644 --- a/clients/cli/utils.c +++ b/clients/cli/utils.c @@ -75,6 +75,7 @@ _meta_type_nmc_generic_info_get_fcn (const NMMetaAbstractInfo *abstract_info, NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, + gboolean *out_is_default, gpointer *out_to_free) { const NmcMetaGenericInfo *info = (const NmcMetaGenericInfo *) abstract_info; @@ -97,6 +98,7 @@ _meta_type_nmc_generic_info_get_fcn (const NMMetaAbstractInfo *abstract_info, get_type, get_flags, out_flags, + out_is_default, out_to_free); } @@ -524,7 +526,7 @@ nmc_count_color_escape_chars (const char *start, const char *end) inside = TRUE; if (inside) num++; - if (*start == 'm') + if (*start == 'm') inside = FALSE; start++; } @@ -603,9 +605,14 @@ int nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquote, char ***argv, int *argc) { + gs_free const char **arr0 = NULL; char **arr; - arr = nmc_strsplit_set (line ? line : "", delim ? delim : " \t", 0); + arr0 = nm_utils_strsplit_set (line ?: "", delim ?: " \t"); + if (!arr0) + arr = g_new0 (char *, 1); + else + arr = g_strdupv ((char **) arr0); if (unquote) { int i = 0; @@ -613,7 +620,7 @@ nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquote, size_t l; const char *quotes = "\"'"; - while (arr && arr[i]) { + while (arr[i]) { s = arr[i]; l = strlen (s); if (l >= 2) { @@ -628,7 +635,6 @@ nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquote, *argv = arr; *argc = g_strv_length (arr); - return 0; } @@ -998,6 +1004,7 @@ typedef struct { const PrintDataCol *col; const char *title; bool title_to_free:1; + bool skip:1; int width; } PrintDataHeaderCell; @@ -1096,6 +1103,7 @@ _print_fill (const NmcConfig *nmc_config, header_cell->col_idx = col_idx; header_cell->col = col; + header_cell->skip = FALSE; header_cell->title = nm_meta_abstract_info_get_name (info, TRUE); if ( nmc_config->multiline_output @@ -1130,10 +1138,11 @@ _print_fill (const NmcConfig *nmc_config, for (i_col = 0; i_col < header_row->len; i_col++) { char *to_free = NULL; PrintDataCell *cell = &cells_line[i_col]; - const PrintDataHeaderCell *header_cell; + PrintDataHeaderCell *header_cell; const NMMetaAbstractInfo *info; NMMetaAccessorGetOutFlags text_out_flags, color_out_flags; gconstpointer value; + gboolean is_default; header_cell = &g_array_index (header_row, PrintDataHeaderCell, i_col); info = header_cell->col->selection_item->info; @@ -1148,7 +1157,11 @@ _print_fill (const NmcConfig *nmc_config, text_get_type, text_get_flags, &text_out_flags, + &is_default, (gpointer *) &to_free); + + header_cell->skip = nmc_config->overview && is_default; + if (NM_FLAGS_HAS (text_out_flags, NM_META_ACCESSOR_GET_OUT_FLAGS_STRV)) { if (value) { if (nmc_config->multiline_output) { @@ -1174,6 +1187,7 @@ _print_fill (const NmcConfig *nmc_config, NM_META_ACCESSOR_GET_TYPE_TERMFORMAT, NM_META_ACCESSOR_GET_FLAGS_NONE, &color_out_flags, + NULL, NULL), &cell->term_color, &cell->term_format); @@ -1231,6 +1245,9 @@ _print_skip_column (const NmcConfig *nmc_config, selection_item = header_cell->col->selection_item; info = selection_item->info; + if (header_cell->skip) + return TRUE; + if (nmc_config->multiline_output) { if (info->meta_type == &nm_meta_type_setting_info_editor) { /* we skip the "name" entry for the setting in multiline output. */ diff --git a/clients/cli/utils.h b/clients/cli/utils.h index ffc5b6f3..c92c4e2e 100644 --- a/clients/cli/utils.h +++ b/clients/cli/utils.h @@ -53,7 +53,6 @@ int nmc_string_to_arg_array (const char *line, const char *delim, gboolean unquo char ***argv, int *argc); const char *nmc_string_is_valid (const char *input, const char **allowed, GError **error); char * nmc_util_strv_for_display (const char *const*strv, gboolean brackets); -char **nmc_strsplit_set (const char *str, const char *delimiter, int max_tokens); int nmc_string_screen_width (const char *start, const char *end); void set_val_str (NmcOutputField fields_array[], guint32 index, char *value); void set_val_strc (NmcOutputField fields_array[], guint32 index, const char *value); @@ -151,6 +150,7 @@ struct _NmcMetaGenericInfo { NMMetaAccessorGetType get_type, NMMetaAccessorGetFlags get_flags, NMMetaAccessorGetOutFlags *out_flags, + gboolean *out_is_default, gpointer *out_to_free); }; |