about summary refs log tree commit diff
path: root/src/nmcli/connections.c
diff options
context:
space:
mode:
authorMichael Biebl <biebl@debian.org>2022-01-13 22:30:39 +0100
committerMichael Biebl <biebl@debian.org>2022-01-13 22:30:39 +0100
commit88c227d90a6b7b388c5c85d72802a0ca8f05ed5c (patch)
tree71f32df6617802270e8a78574bd8e1637dc532f4 /src/nmcli/connections.c
parente74c568b07b50b97873fb4ee1d776dedefbd54d6 (diff)
New upstream version 1.34.0 upstream/1.34.0
Diffstat (limited to 'src/nmcli/connections.c')
-rw-r--r--src/nmcli/connections.c212
1 files changed, 129 insertions, 83 deletions
diff --git a/src/nmcli/connections.c b/src/nmcli/connections.c
index 9f700cae..5edd33f0 100644
--- a/src/nmcli/connections.c
+++ b/src/nmcli/connections.c
@@ -11,8 +11,12 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <signal.h>
+#if HAVE_EDITLINE_READLINE
+#include <editline/readline.h>
+#else
 #include <readline/readline.h>
 #include <readline/history.h>
+#endif
 #include <fcntl.h>
 
 #include "libnm-glib-aux/nm-dbus-aux.h"
@@ -201,24 +205,24 @@ nmc_active_connection_cmp(NMActiveConnection *ac_a, NMActiveConnection *ac_b)
     conn = nm_active_connection_get_connection(ac_a);
     s_ip = conn ? nm_connection_get_setting_ip6_config(NM_CONNECTION(conn)) : NULL;
     if (s_ip
-        && strcmp(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0)
+        && nm_streq(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP6_CONFIG_METHOD_SHARED))
         cmp++;
     conn = nm_active_connection_get_connection(ac_b);
     s_ip = conn ? nm_connection_get_setting_ip6_config(NM_CONNECTION(conn)) : NULL;
     if (s_ip
-        && strcmp(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP6_CONFIG_METHOD_SHARED) == 0)
+        && nm_streq(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP6_CONFIG_METHOD_SHARED))
         cmp--;
     NM_CMP_RETURN(cmp);
 
     conn = nm_active_connection_get_connection(ac_a);
     s_ip = conn ? nm_connection_get_setting_ip4_config(NM_CONNECTION(conn)) : NULL;
     if (s_ip
-        && strcmp(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0)
+        && nm_streq(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP4_CONFIG_METHOD_SHARED))
         cmp++;
     conn = nm_active_connection_get_connection(ac_b);
     s_ip = conn ? nm_connection_get_setting_ip4_config(NM_CONNECTION(conn)) : NULL;
     if (s_ip
-        && strcmp(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP4_CONFIG_METHOD_SHARED) == 0)
+        && nm_streq(nm_setting_ip_config_get_method(s_ip), NM_SETTING_IP4_CONFIG_METHOD_SHARED))
         cmp--;
     NM_CMP_RETURN(cmp);
 
@@ -870,18 +874,19 @@ const NmcMetaGenericInfo
     "," NM_SETTING_CDMA_SETTING_NAME "," NM_SETTING_BLUETOOTH_SETTING_NAME             \
     "," NM_SETTING_OLPC_MESH_SETTING_NAME "," NM_SETTING_VPN_SETTING_NAME              \
     "," NM_SETTING_INFINIBAND_SETTING_NAME "," NM_SETTING_BOND_SETTING_NAME            \
-    "," NM_SETTING_VLAN_SETTING_NAME "," NM_SETTING_BRIDGE_SETTING_NAME                \
-    "," NM_SETTING_BRIDGE_PORT_SETTING_NAME "," NM_SETTING_TEAM_SETTING_NAME           \
-    "," NM_SETTING_TEAM_PORT_SETTING_NAME "," NM_SETTING_OVS_BRIDGE_SETTING_NAME       \
-    "," NM_SETTING_OVS_INTERFACE_SETTING_NAME "," NM_SETTING_OVS_PATCH_SETTING_NAME    \
-    "," NM_SETTING_OVS_PORT_SETTING_NAME "," NM_SETTING_DCB_SETTING_NAME               \
-    "," NM_SETTING_TUN_SETTING_NAME "," NM_SETTING_IP_TUNNEL_SETTING_NAME              \
-    "," NM_SETTING_MACSEC_SETTING_NAME "," NM_SETTING_MACVLAN_SETTING_NAME             \
-    "," NM_SETTING_VXLAN_SETTING_NAME "," NM_SETTING_VRF_SETTING_NAME                  \
-    "," NM_SETTING_WPAN_SETTING_NAME "," NM_SETTING_6LOWPAN_SETTING_NAME               \
-    "," NM_SETTING_WIREGUARD_SETTING_NAME "," NM_SETTING_PROXY_SETTING_NAME            \
-    "," NM_SETTING_TC_CONFIG_SETTING_NAME "," NM_SETTING_SRIOV_SETTING_NAME            \
-    "," NM_SETTING_ETHTOOL_SETTING_NAME "," NM_SETTING_OVS_DPDK_SETTING_NAME           \
+    "," NM_SETTING_BOND_PORT_SETTING_NAME "," NM_SETTING_VLAN_SETTING_NAME             \
+    "," NM_SETTING_BRIDGE_SETTING_NAME "," NM_SETTING_BRIDGE_PORT_SETTING_NAME         \
+    "," NM_SETTING_TEAM_SETTING_NAME "," NM_SETTING_TEAM_PORT_SETTING_NAME             \
+    "," NM_SETTING_OVS_BRIDGE_SETTING_NAME "," NM_SETTING_OVS_INTERFACE_SETTING_NAME   \
+    "," NM_SETTING_OVS_PATCH_SETTING_NAME "," NM_SETTING_OVS_PORT_SETTING_NAME         \
+    "," NM_SETTING_DCB_SETTING_NAME "," NM_SETTING_TUN_SETTING_NAME                    \
+    "," NM_SETTING_IP_TUNNEL_SETTING_NAME "," NM_SETTING_MACSEC_SETTING_NAME           \
+    "," NM_SETTING_MACVLAN_SETTING_NAME "," NM_SETTING_VXLAN_SETTING_NAME              \
+    "," NM_SETTING_VRF_SETTING_NAME "," NM_SETTING_WPAN_SETTING_NAME                   \
+    "," NM_SETTING_6LOWPAN_SETTING_NAME "," NM_SETTING_WIREGUARD_SETTING_NAME          \
+    "," NM_SETTING_PROXY_SETTING_NAME "," NM_SETTING_TC_CONFIG_SETTING_NAME            \
+    "," NM_SETTING_SRIOV_SETTING_NAME "," NM_SETTING_ETHTOOL_SETTING_NAME              \
+    "," NM_SETTING_OVS_DPDK_SETTING_NAME                                               \
     "," NM_SETTING_HOSTNAME_SETTING_NAME /* NM_SETTING_DUMMY_SETTING_NAME NM_SETTING_WIMAX_SETTING_NAME */
 
 const NmcMetaGenericInfo *const nmc_fields_con_active_details_groups[] = {
@@ -1058,7 +1063,8 @@ usage_connection_add(void)
                  "                  [arp-interval <num>]\n"
                  "                  [arp-ip-target <num>]\n"
                  "                  [lacp-rate slow (0) | fast (1)]\n\n"
-                 "    bond-slave:   master <master (ifname, or connection UUID or name)>\n\n"
+                 "    bond-slave:   master <master (ifname, or connection UUID or name)>\n"
+                 "                  [queue-id <0-65535>]\n\n"
                  "    team:         [config <file>|<raw JSON data>]\n\n"
                  "    team-slave:   master <master (ifname, or connection UUID or name)>\n"
                  "                  [config <file>|<raw JSON data>]\n\n"
@@ -1121,6 +1127,7 @@ usage_connection_add(void)
                  "                  [path-cost <1-65535>]\n"
                  "                  [hairpin yes|no]\n\n"
                  "    team:         [config <file>|<raw JSON data>]\n\n"
+                 "    bond:         [queue-id <0-65535>]\n\n"
                  "  IP_OPTIONS:\n"
                  "                  [ip4 <IPv4 address>] [gw4 <IPv4 gateway>]\n"
                  "                  [ip6 <IPv6 address>] [gw6 <IPv6 gateway>]\n\n"));
@@ -1662,7 +1669,7 @@ split_required_fields_for_con_show(const char *input,
     str1 = g_string_new(NULL);
     str2 = g_string_new(NULL);
 
-    fields = nm_utils_strsplit_set_with_empty(input, ",");
+    fields = nm_strsplit_set_with_empty(input, ",");
     for (iter = fields; iter && *iter; iter++) {
         char *   s_mutable = (char *) (*iter);
         char *   dot;
@@ -2003,7 +2010,7 @@ parse_preferred_connection_order(const char *order, GError **error)
     gboolean             inverse, unique;
     guint                i;
 
-    strv = nm_utils_strsplit_set(order, ":");
+    strv = nm_strsplit_set(order, ":");
     if (!strv) {
         g_set_error(error, NMCLI_ERROR, 0, _("incorrect string '%s' of '--order' option"), order);
         return NULL;
@@ -2463,7 +2470,7 @@ find_device_for_connection(NmCli *       nmc,
     g_assert(s_con);
     con_type = nm_setting_connection_get_connection_type(s_con);
 
-    if (strcmp(con_type, NM_SETTING_VPN_SETTING_NAME) == 0) {
+    if (nm_streq(con_type, NM_SETTING_VPN_SETTING_NAME)) {
         /* VPN connections */
         NMActiveConnection *active = NULL;
         if (iface) {
@@ -2488,8 +2495,9 @@ find_device_for_connection(NmCli *       nmc,
         }
     } else {
         /* Other connections */
-        NMDevice *       found_device = NULL;
-        const GPtrArray *devices      = nm_client_get_devices(nmc->client);
+        NMDevice *       found_device           = NULL;
+        const GPtrArray *devices                = nm_client_get_devices(nmc->client);
+        gboolean         found_device_with_name = FALSE;
 
         for (i = 0; i < devices->len && !found_device; i++) {
             NMDevice *dev = g_ptr_array_index(devices, i);
@@ -2499,6 +2507,7 @@ find_device_for_connection(NmCli *       nmc,
                 if (!nm_streq0(dev_iface, iface))
                     continue;
 
+                found_device_with_name = TRUE;
                 if (!nm_device_connection_compatible(dev, connection, error)) {
                     g_prefix_error(error,
                                    _("device '%s' not compatible with connection '%s': "),
@@ -2535,12 +2544,21 @@ find_device_for_connection(NmCli *       nmc,
 
         if (!found_device) {
             if (iface) {
-                g_set_error(error,
-                            NMCLI_ERROR,
-                            0,
-                            _("device '%s' not compatible with connection '%s'"),
-                            iface,
-                            nm_setting_connection_get_id(s_con));
+                if (found_device_with_name) {
+                    g_set_error(error,
+                                NMCLI_ERROR,
+                                0,
+                                _("device '%s' not compatible with connection '%s'"),
+                                iface,
+                                nm_setting_connection_get_id(s_con));
+                } else {
+                    g_set_error(error,
+                                NMCLI_ERROR,
+                                0,
+                                _("device '%s' not found for connection '%s'"),
+                                iface,
+                                nm_setting_connection_get_id(s_con));
+                }
             } else {
                 g_set_error(error,
                             NMCLI_ERROR,
@@ -2833,8 +2851,7 @@ nmc_activate_connection(NmCli *             nmc,
                                                   &spec_object,
                                                   &local);
 
-        /* Virtual connection may not have their interfaces created yet */
-        if (!device_found && !nm_connection_is_virtual(connection)) {
+        if (!device_found) {
             g_set_error(error, NMCLI_ERROR, NMC_RESULT_ERROR_CON_ACTIVATION, "%s", local->message);
             return FALSE;
         }
@@ -2947,7 +2964,7 @@ do_connection_up(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const
         argc_ptr = &arg_num;
     }
 
-    if (argc > 0 && strcmp(*argv, "ifname") != 0) {
+    if (argc > 0 && !nm_streq(*argv, "ifname")) {
         connection = get_connection(nmc, argc_ptr, argv_ptr, NULL, NULL, NULL, &error);
         if (!connection) {
             g_string_printf(nmc->return_text, _("Error: %s."), error->message);
@@ -2960,7 +2977,7 @@ do_connection_up(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const
         if (argc == 1 && nmc->complete)
             nmc_complete_strings(*argv, "ifname", "ap", "passwd-file");
 
-        if (strcmp(*argv, "ifname") == 0) {
+        if (nm_streq(*argv, "ifname")) {
             argc--;
             argv++;
             if (!argc) {
@@ -2972,7 +2989,7 @@ do_connection_up(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const
             ifname = *argv;
             if (argc == 1 && nmc->complete)
                 nmc_complete_device(nmc->client, ifname, ap != NULL);
-        } else if (strcmp(*argv, "ap") == 0) {
+        } else if (nm_streq(*argv, "ap")) {
             argc--;
             argv++;
             if (!argc) {
@@ -2984,7 +3001,7 @@ do_connection_up(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const
             ap = *argv;
             if (argc == 1 && nmc->complete)
                 nmc_complete_bssid(nmc->client, ifname, ap);
-        } else if (strcmp(*argv, "passwd-file") == 0) {
+        } else if (nm_streq(*argv, "passwd-file")) {
             argc--;
             argv++;
             if (!argc) {
@@ -3652,7 +3669,7 @@ is_setting_mandatory(NMConnection *connection, NMSetting *setting)
         else
             item = nm_meta_setting_info_valid_parts_for_slave_type(s_type, NULL);
         for (; item && *item; item++) {
-            if (!strcmp(name, (*item)->setting_info->general->setting_name))
+            if (nm_streq(name, (*item)->setting_info->general->setting_name))
                 return (*item)->mandatory;
         }
     }
@@ -3721,11 +3738,11 @@ normalized_master_for_slave(const GPtrArray *connections,
         s_con      = nm_connection_get_setting_connection(connection);
         g_assert(s_con);
         con_type = nm_setting_connection_get_connection_type(s_con);
-        if (type && g_strcmp0(con_type, type) != 0)
+        if (type && !nm_streq0(con_type, type))
             continue;
         if (func) {
             /* There was a prefix; only compare to that type. */
-            if (g_strcmp0(master, func(connection)) == 0) {
+            if (nm_streq0(master, func(connection))) {
                 if (out_type)
                     *out_type = con_type;
                 if (func == nm_connection_get_id)
@@ -3738,13 +3755,13 @@ normalized_master_for_slave(const GPtrArray *connections,
             id     = nm_connection_get_id(connection);
             uuid   = nm_connection_get_uuid(connection);
             ifname = nm_connection_get_interface_name(connection);
-            if (g_strcmp0(master, uuid) == 0 || g_strcmp0(master, ifname) == 0) {
+            if (NM_IN_STRSET(master, uuid, ifname)) {
                 out_master = master;
                 if (out_type)
                     *out_type = con_type;
                 break;
             }
-            if (!found_by_id && g_strcmp0(master, id) == 0) {
+            if (!found_by_id && nm_streq0(master, id)) {
                 out_type_by_id = con_type;
                 found_by_id    = uuid;
             }
@@ -3777,13 +3794,13 @@ prompt_yes_no(gboolean default_yes, char *delim)
     if (!delim)
         delim = "";
 
-    snprintf(prompt,
-             sizeof(prompt),
-             "(%s/%s) [%s]%s ",
-             WORD_YES,
-             WORD_NO,
-             default_yes ? WORD_YES : WORD_NO,
-             delim);
+    g_snprintf(prompt,
+               sizeof(prompt),
+               "(%s/%s) [%s]%s ",
+               WORD_YES,
+               WORD_NO,
+               default_yes ? WORD_YES : WORD_NO,
+               delim);
 
     return prompt;
 }
@@ -4352,10 +4369,11 @@ set_connection_type(NmCli *           nmc,
     }
 
     /* ifname is mandatory for all connection types except virtual ones (bond, team, bridge, vlan) */
-    if ((strcmp(value, NM_SETTING_BOND_SETTING_NAME) == 0)
-        || (strcmp(value, NM_SETTING_TEAM_SETTING_NAME) == 0)
-        || (strcmp(value, NM_SETTING_BRIDGE_SETTING_NAME) == 0)
-        || (strcmp(value, NM_SETTING_VLAN_SETTING_NAME) == 0)) {
+    if (NM_IN_STRSET(value,
+                     NM_SETTING_BOND_SETTING_NAME,
+                     NM_SETTING_TEAM_SETTING_NAME,
+                     NM_SETTING_BRIDGE_SETTING_NAME,
+                     NM_SETTING_VLAN_SETTING_NAME)) {
         disable_options(NM_SETTING_CONNECTION_SETTING_NAME, NM_SETTING_CONNECTION_INTERFACE_NAME);
     }
 
@@ -4386,7 +4404,7 @@ set_connection_iface(NmCli *           nmc,
 {
     if (value) {
         /* Special value of '*' means no specific interface name */
-        if (strcmp(value, "*") == 0)
+        if (nm_streq(value, "*"))
             value = NULL;
     }
 
@@ -4541,19 +4559,17 @@ set_bluetooth_type(NmCli *           nmc,
         return TRUE;
 
     /* 'dun' type requires adding 'gsm' or 'cdma' setting */
-    if (!strcmp(value, NM_SETTING_BLUETOOTH_TYPE_DUN)
-        || !strcmp(value, NM_SETTING_BLUETOOTH_TYPE_DUN "-gsm")) {
+    if (NM_IN_STRSET(value, NM_SETTING_BLUETOOTH_TYPE_DUN, NM_SETTING_BLUETOOTH_TYPE_DUN "-gsm")) {
         value   = NM_SETTING_BLUETOOTH_TYPE_DUN;
         setting = nm_meta_setting_info_editor_new_setting(
             &nm_meta_setting_infos_editor[NM_META_SETTING_TYPE_GSM],
             NM_META_ACCESSOR_SETTING_INIT_TYPE_CLI);
         nm_connection_add_setting(con, setting);
-    } else if (!strcmp(value, NM_SETTING_BLUETOOTH_TYPE_DUN "-cdma")) {
+    } else if (NM_IN_STRSET(value, NM_SETTING_BLUETOOTH_TYPE_DUN "-cdma")) {
         value   = NM_SETTING_BLUETOOTH_TYPE_DUN;
         setting = nm_setting_cdma_new();
         nm_connection_add_setting(con, setting);
-    } else if (!strcmp(value, NM_SETTING_BLUETOOTH_TYPE_PANU)
-               || !strcmp(value, NM_SETTING_BLUETOOTH_TYPE_NAP)) {
+    } else if (NM_IN_STRSET(value, NM_SETTING_BLUETOOTH_TYPE_PANU, NM_SETTING_BLUETOOTH_TYPE_NAP)) {
         /* no op */
     } else {
         g_set_error(error,
@@ -5605,13 +5621,13 @@ read_properties:
     g_clear_error(&error);
     /* Get the arguments from the command line if any */
     if (argc && !nmc_process_connection_properties(nmc, connection, &argc, &argv, FALSE, &error)) {
-        if (g_strcmp0(*argv, "--") == 0 && !seen_dash_dash) {
+        if (nm_streq0(*argv, "--") && !seen_dash_dash) {
             /* This is for compatibility with older nmcli that required
              * options and properties to be separated with "--" */
             seen_dash_dash = TRUE;
             next_arg(nmc, &argc, &argv, NULL);
             goto read_properties;
-        } else if (g_strcmp0(*argv, "save") == 0) {
+        } else if (nm_streq0(*argv, "save")) {
             /* It would be better if "save" was a separate argument and not
              * mixed with properties, but there's not much we can do about it now. */
             argc--;
@@ -5746,6 +5762,9 @@ finish:
 /*****************************************************************************/
 /* Functions for readline TAB completion in editor */
 
+#if HAVE_EDITLINE_READLINE
+#define uuid_display_hook ((void (*)(void)) NULL)
+#else
 static void
 uuid_display_hook(char **array, int len, int max_len)
 {
@@ -5769,6 +5788,7 @@ uuid_display_hook(char **array, int len, int max_len)
     rl_display_match_list(array, len, max_len + max + 3);
     rl_forced_update_display();
 }
+#endif
 
 static char *
 gen_nmcli_cmds_menu(const char *text, int state)
@@ -5990,6 +6010,8 @@ gen_property_names(const char *text, int state)
             slv_type = NM_SETTING_TEAM_SETTING_NAME;
         else if (nm_streq0(strv[0], NM_SETTING_BRIDGE_PORT_SETTING_NAME))
             slv_type = NM_SETTING_BRIDGE_SETTING_NAME;
+        else if (nm_streq0(strv[0], NM_SETTING_BOND_PORT_SETTING_NAME))
+            slv_type = NM_SETTING_BOND_SETTING_NAME;
         else
             slv_type = NULL;
         valid_settings_slave = nm_meta_setting_info_valid_parts_for_slave_type(slv_type, NULL);
@@ -6071,7 +6093,7 @@ _create_vpn_array(const GPtrArray *connections, gboolean uuid)
         NMConnection *connection = NM_CONNECTION(connections->pdata[c]);
         const char *  type       = nm_connection_get_connection_type(connection);
 
-        if (g_strcmp0(type, NM_SETTING_VPN_SETTING_NAME) == 0)
+        if (nm_streq0(type, NM_SETTING_VPN_SETTING_NAME))
             array[idx++] =
                 uuid ? nm_connection_get_uuid(connection) : nm_connection_get_id(connection);
     }
@@ -6440,8 +6462,10 @@ gen_property_values(const char *text, int state)
     return nmc_rl_gen_func_basic(text, state, avals);
 }
 
+#if !HAVE_EDITLINE_READLINE
 /* from readline */
 extern int rl_complete_with_tilde_expansion;
+#endif
 
 /*
  * Attempt to complete on the contents of TEXT.  START and END show the
@@ -6469,8 +6493,10 @@ nmcli_editor_tab_completion(const char *text, int start, int end)
     /* Disable default filename completion */
     rl_attempted_completion_over = 1;
 
+#if !HAVE_EDITLINE_READLINE
     /* Enable tilde expansion when filenames are completed */
     rl_complete_with_tilde_expansion = 1;
+#endif
 
     /* Filter out possible ANSI color escape sequences */
     prompt_tmp = nmc_filter_out_colors((const char *) rl_prompt);
@@ -6479,11 +6505,11 @@ nmcli_editor_tab_completion(const char *text, int start, int end)
     n1 = strspn(line, " \t");
 
     /* Choose the right generator function */
-    if (strcmp(prompt_tmp, EDITOR_PROMPT_CON_TYPE) == 0)
+    if (nm_streq(prompt_tmp, EDITOR_PROMPT_CON_TYPE))
         generator_func = gen_connection_types(text);
-    else if (strcmp(prompt_tmp, EDITOR_PROMPT_SETTING) == 0)
+    else if (nm_streq(prompt_tmp, EDITOR_PROMPT_SETTING))
         generator_func = gen_setting_names;
-    else if (strcmp(prompt_tmp, EDITOR_PROMPT_PROPERTY) == 0)
+    else if (nm_streq(prompt_tmp, EDITOR_PROMPT_PROPERTY))
         generator_func = gen_property_names;
     else if (g_str_has_suffix(rl_prompt, prompt_yes_no(TRUE, NULL))
              || g_str_has_suffix(rl_prompt, prompt_yes_no(FALSE, NULL)))
@@ -6759,7 +6785,7 @@ parse_editor_main_cmd(const char *cmd, char **cmd_arg)
         editor_cmd = NMC_EDITOR_MAIN_CMD_ACTIVATE;
     else if (matches(cmd_arg0, "back"))
         editor_cmd = NMC_EDITOR_MAIN_CMD_BACK;
-    else if (matches(cmd_arg0, "help") || strcmp(cmd_arg0, "?") == 0)
+    else if (matches(cmd_arg0, "help") || nm_streq(cmd_arg0, "?"))
         editor_cmd = NMC_EDITOR_MAIN_CMD_HELP;
     else if (matches(cmd_arg0, "quit"))
         editor_cmd = NMC_EDITOR_MAIN_CMD_QUIT;
@@ -6946,7 +6972,7 @@ parse_editor_sub_cmd(const char *cmd, char **cmd_arg)
         editor_cmd = NMC_EDITOR_SUB_CMD_PRINT;
     else if (matches(cmd_arg0, "back"))
         editor_cmd = NMC_EDITOR_SUB_CMD_BACK;
-    else if (matches(cmd_arg0, "help") || strcmp(cmd_arg0, "?") == 0)
+    else if (matches(cmd_arg0, "help") || nm_streq(cmd_arg0, "?"))
         editor_cmd = NMC_EDITOR_SUB_CMD_HELP;
     else if (matches(cmd_arg0, "quit"))
         editor_cmd = NMC_EDITOR_SUB_CMD_QUIT;
@@ -7356,8 +7382,8 @@ property_edit_submenu(NmCli *              nmc,
 
         case NMC_EDITOR_SUB_CMD_CHANGE:
             rl_startup_hook = nmc_rl_set_deftext;
-            nmc_rl_pre_input_deftext =
-                nmc_setting_get_property_parsable(curr_setting, prop_name, NULL);
+            nm_strdup_reset_take(&nmc_rl_pre_input_deftext,
+                                 nmc_setting_get_property_parsable(curr_setting, prop_name, NULL));
             prop_val_user = nmc_readline(&nmc->nmc_config, _("Edit '%s' value: "), prop_name);
 
             if (!nmc_setting_set_property(nmc->client,
@@ -8161,12 +8187,12 @@ editor_menu_main(NmCli *nmc, NMConnection *connection, const char *connection_ty
 
         case NMC_EDITOR_MAIN_CMD_VERIFY:
             /* Verify current setting or the whole connection */
-            if (cmd_arg && strcmp(cmd_arg, "all") && strcmp(cmd_arg, "fix")) {
+            if (cmd_arg && !nm_streq(cmd_arg, "all") && !nm_streq(cmd_arg, "fix")) {
                 g_print(_("Invalid verify option: %s\n"), cmd_arg);
                 break;
             }
 
-            if (menu_ctx.curr_setting && (!cmd_arg || strcmp(cmd_arg, "all") != 0)) {
+            if (menu_ctx.curr_setting && (!cmd_arg || !nm_streq(cmd_arg, "all"))) {
                 gs_free_error GError *tmp_err = NULL;
 
                 nm_setting_verify(menu_ctx.curr_setting, NULL, &tmp_err);
@@ -8524,7 +8550,7 @@ editor_init_new_connection(NmCli *nmc, NMConnection *connection, const char *sla
         set_default_interface_name(nmc, s_con);
 
         /* Set sensible initial VLAN values */
-        if (g_strcmp0(con_type, NM_SETTING_VLAN_SETTING_NAME) == 0) {
+        if (nm_streq0(con_type, NM_SETTING_VLAN_SETTING_NAME)) {
             const char *dev_ifname = get_ethernet_device_name(nmc);
 
             g_object_set(NM_SETTING_VLAN(base_setting),
@@ -9235,10 +9261,11 @@ do_connection_reload(const NMCCommand *cmd, NmCli *nmc, int argc, const char *co
 static void
 do_connection_load(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
 {
-    GError *             error     = NULL;
-    gs_free const char **filenames = NULL;
-    gs_strfreev char **  failures  = NULL;
-    int                  i;
+    GError *           error       = NULL;
+    gs_strfreev char **filenames   = NULL;
+    gs_strfreev char **failures    = NULL;
+    gs_free char *     current_dir = NULL;
+    int                i;
 
     next_arg(nmc, &argc, &argv, NULL);
     if (argc == 0) {
@@ -9252,7 +9279,24 @@ do_connection_load(const NMCCommand *cmd, NmCli *nmc, int argc, const char *cons
         return;
     }
 
-    filenames = (const char **) nm_utils_strv_dup(argv, argc, FALSE);
+    filenames = nm_strv_dup(argv, argc, TRUE);
+
+    current_dir = g_get_current_dir();
+    if (filenames && current_dir && current_dir[0] == '/' && current_dir[1] != '/') {
+        for (i = 0; filenames[i]; i++) {
+            char *f = filenames[i];
+
+            if (f[0] == '\0' || f[0] == '/')
+                continue;
+
+            /* Don't use g_canonicalize_filename(), because we want to keep
+             * the argv argument closely to what the user provided. We will get
+             * that path back as "failures" below, so don't perform additional
+             * normalization except prepending the $PWD. */
+            filenames[i] = g_build_filename(current_dir, f, NULL);
+            g_free(f);
+        }
+    }
 
     nm_client_load_connections(nmc->client, (char **) filenames, &failures, NULL, &error);
     if (error) {
@@ -9311,7 +9355,7 @@ do_connection_import(const NMCCommand *cmd, NmCli *nmc, int argc, const char *co
             nmc_complete_strings(*argv, type ? NULL : "type", filename ? NULL : "file");
         }
 
-        if (strcmp(*argv, "type") == 0) {
+        if (nm_streq(*argv, "type")) {
             argc--;
             argv++;
             if (!argc) {
@@ -9333,7 +9377,7 @@ do_connection_import(const NMCCommand *cmd, NmCli *nmc, int argc, const char *co
             else
                 g_printerr(_("Warning: 'type' already specified, ignoring extra one.\n"));
 
-        } else if (strcmp(*argv, "file") == 0) {
+        } else if (nm_streq(*argv, "file")) {
             argc--;
             argv++;
             if (!argc) {
@@ -9465,7 +9509,7 @@ do_connection_export(const NMCCommand *cmd, NmCli *nmc, int argc, const char *co
     }
 
     type = nm_connection_get_connection_type(connection);
-    if (g_strcmp0(type, NM_SETTING_VPN_SETTING_NAME) != 0) {
+    if (!nm_streq0(type, NM_SETTING_VPN_SETTING_NAME)) {
         g_string_printf(nmc->return_text, _("Error: the connection is not VPN."));
         nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
         goto finish;
@@ -9587,7 +9631,7 @@ nmcli_con_tab_completion(const char *text, int start, int end)
     /* Disable readline's default filename completion */
     rl_attempted_completion_over = 1;
 
-    if (g_strcmp0(rl_prompt, PROMPT_CONNECTION) == 0) {
+    if (nm_streq0(rl_prompt, PROMPT_CONNECTION)) {
         /* Disable appending space after completion */
         rl_completion_append_character = '\0';
 
@@ -9595,18 +9639,20 @@ nmcli_con_tab_completion(const char *text, int start, int end)
             return NULL;
 
         generator_func = gen_func_connection_names;
-    } else if (g_strcmp0(rl_prompt, PROMPT_CONNECTIONS) == 0) {
+    } else if (nm_streq0(rl_prompt, PROMPT_CONNECTIONS)) {
         generator_func = gen_func_connection_names;
-    } else if (g_strcmp0(rl_prompt, PROMPT_ACTIVE_CONNECTIONS) == 0) {
+    } else if (nm_streq0(rl_prompt, PROMPT_ACTIVE_CONNECTIONS)) {
         generator_func = gen_func_active_connection_names;
     } else if (rl_prompt && g_str_has_prefix(rl_prompt, NM_META_TEXT_PROMPT_VPN_TYPE)) {
         info = (const NMMetaAbstractInfo *) nm_meta_property_info_vpn_service_type;
         nmc_tab_completion.words = _meta_abstract_complete(info, text);
         generator_func           = _meta_abstract_generator;
-    } else if (g_strcmp0(rl_prompt, PROMPT_IMPORT_FILE) == 0) {
-        rl_attempted_completion_over     = 0;
+    } else if (nm_streq0(rl_prompt, PROMPT_IMPORT_FILE)) {
+        rl_attempted_completion_over = 0;
+#if !HAVE_EDITLINE_READLINE
         rl_complete_with_tilde_expansion = 1;
-    } else if (g_strcmp0(rl_prompt, PROMPT_VPN_CONNECTION) == 0) {
+#endif
+    } else if (nm_streq0(rl_prompt, PROMPT_VPN_CONNECTION)) {
         generator_func = gen_vpn_ids;
     }