about summary refs log tree commit diff
path: root/clients/cli/nmcli.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/cli/nmcli.c')
-rw-r--r--clients/cli/nmcli.c120
1 files changed, 69 insertions, 51 deletions
diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c
index 5fbd6d72..ee5ef015 100644
--- a/clients/cli/nmcli.c
+++ b/clients/cli/nmcli.c
@@ -25,8 +25,6 @@
 #include "common.h"
 #include "connections.h"
 #include "devices.h"
-#include "general.h"
-#include "agent.h"
 #include "settings.h"
 
 #if defined(NM_DIST_VERSION)
@@ -72,7 +70,7 @@
 	[NM_META_COLOR_ENABLED]                  = "32", \
 	[NM_META_COLOR_DISABLED]                 = "31", \
 
-NmCli nm_cli = {
+static NmCli nm_cli = {
 	.client = NULL,
 
 	.return_value = NMC_RESULT_SUCCESS,
@@ -101,6 +99,9 @@ NmCli nm_cli = {
 	.editor_save_confirmation = TRUE,
 };
 
+const NmCli *const nm_cli_global_readline = &nm_cli;
+const NmCli *const nmc_meta_environment_arg = &nm_cli;
+
 /*****************************************************************************/
 
 typedef struct {
@@ -255,21 +256,21 @@ usage (void)
 	              "\n"));
 }
 
-static const NMCCommand nmcli_cmds[] = {
-	{ "general",     do_general,      NULL,   FALSE,  FALSE },
-	{ "monitor",     do_monitor,      NULL,   TRUE,   FALSE },
-	{ "networking",  do_networking,   NULL,   FALSE,  FALSE },
-	{ "radio",       do_radio,        NULL,   FALSE,  FALSE },
-	{ "connection",  do_connections,  NULL,   FALSE,  FALSE },
-	{ "device",      do_devices,      NULL,   FALSE,  FALSE },
-	{ "agent",       do_agent,        NULL,   FALSE,  FALSE },
-	{ NULL,          do_overview,     usage,  TRUE,   TRUE },
-};
-
 static gboolean
-matches_arg (NmCli *nmc, int *argc, char ***argv, const char *pattern, char **arg)
+matches_arg (NmCli *nmc,
+             int *argc,
+             const char *const**argv,
+             const char *pattern,
+             char **arg)
 {
-	char *opt = *argv[0];
+	gs_free char *opt_free = NULL;
+	const char *opt = (*argv)[0];
+	gs_free char *arg_tmp = NULL;
+	const char *s;
+
+	nm_assert (opt);
+	nm_assert (opt[0] == '-');
+	nm_assert (!arg || !*arg);
 
 	if (nmc->return_value != NMC_RESULT_SUCCESS) {
 		/* Don't process further matches if there has been an error. */
@@ -285,33 +286,31 @@ matches_arg (NmCli *nmc, int *argc, char ***argv, const char *pattern, char **ar
 	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)++;
+		s = strchr (opt, '=');
+		if (s) {
+			opt = nm_strndup_a (300, opt, s - opt, &opt_free);
+			arg_tmp = g_strdup (&s[1]);
 		}
 	}
 
-	if (!matches (opt, pattern)) {
-		if (arg && *arg) {
-			/* Back off the replacement of "=". */
-			(*arg)--;
-			**arg = '=';
-		}
+	if (!matches (opt, pattern))
 		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;
+	if (arg) {
+		if (arg_tmp)
+			*arg = g_steal_pointer (&arg_tmp);
+		else {
+			/* We need a value, but the option didn't contain a "=<value>" part.
+			 * Proceed to the next argument. */
+			if (*argc <= 1) {
+				g_string_printf (nmc->return_text, _("Error: missing argument for '%s' option."), opt);
+				nmc->return_value = NMC_RESULT_ERROR_USER_INPUT;
+				return FALSE;
+			}
+			(*argc)--;
+			(*argv)++;
+			*arg = g_strdup (*argv[0]);
 		}
-		*arg = *argv[0];
 	}
 
 	return TRUE;
@@ -697,26 +696,43 @@ set_colors (NmcColorOption color_option,
 /*************************************************************************************/
 
 static gboolean
-process_command_line (NmCli *nmc, int argc, char **argv)
+process_command_line (NmCli *nmc, int argc, char **argv_orig)
 {
+	static const NMCCommand nmcli_cmds[] = {
+		{ "general",    nmc_command_func_general,     NULL,  FALSE, FALSE },
+		{ "monitor",    nmc_command_func_monitor,     NULL,  TRUE,  FALSE },
+		{ "networking", nmc_command_func_networking,  NULL,  FALSE, FALSE },
+		{ "radio",      nmc_command_func_radio,       NULL,  FALSE, FALSE },
+		{ "connection", nmc_command_func_connection,  NULL,  FALSE, FALSE },
+		{ "device",     nmc_command_func_device,      NULL,  FALSE, FALSE },
+		{ "agent",      nmc_command_func_agent,       NULL,  FALSE, FALSE },
+		{ NULL,         nmc_command_func_overview,    usage, TRUE,  TRUE },
+	};
 	NmcColorOption colors = NMC_USE_COLOR_AUTO;
-	char *base;
+	const char *base;
+	const char *const*argv;
 
-	base = strrchr (argv[0], '/');
+	base = strrchr (argv_orig[0], '/');
 	if (base == NULL)
-		base = argv[0];
+		base = argv_orig[0];
 	else
 		base++;
-	if (argc > 1 && nm_streq (argv[1], "--complete-args")) {
+
+	if (   argc > 1
+	    && nm_streq (argv_orig[1], "--complete-args")) {
 		nmc->complete = TRUE;
-		argv[1] = argv[0];
-		next_arg (nmc, &argc, &argv, NULL);
+		argv_orig[1] = argv_orig[0];
+		argc--;
+		argv_orig++;
 	}
+
+	argv = (const char *const*) argv_orig;
+
 	next_arg (nmc, &argc, &argv, NULL);
 
 	/* parse options */
 	while (argc) {
-		char *value;
+		gs_free char *value = NULL;
 
 		if (argv[0][0] != '-')
 			break;
@@ -909,11 +925,12 @@ signal_handler (gpointer user_data)
 }
 
 void
-nm_cli_spawn_pager (NmCli *nmc)
+nm_cli_spawn_pager (const NmcConfig *nmc_config,
+                    NmcPagerData *pager_data)
 {
-	if (nmc->pager_pid > 0)
+	if (pager_data->pid != 0)
 		return;
-	nmc->pager_pid = nmc_terminal_spawn_pager (&nmc->nmc_config);
+	pager_data->pid = nmc_terminal_spawn_pager (nmc_config);
 }
 
 static void
@@ -935,13 +952,14 @@ nmc_cleanup (NmCli *nmc)
 
 	nm_clear_g_free (&nmc->required_fields);
 
-	if (nmc->pager_pid > 0) {
+	if (nmc->pager_data.pid != 0) {
+		pid_t pid = nm_steal_int (&nmc->pager_data.pid);
+
 		fclose (stdout);
 		fclose (stderr);
 		do {
-			ret = waitpid (nmc->pager_pid, NULL, 0);
+			ret = waitpid (pid, NULL, 0);
 		} while (ret == -1 && errno == EINTR);
-		nmc->pager_pid = 0;
 	}
 
 	nm_clear_g_free (&nmc->palette_buffer);