diff cli-runopts.c @ 1173:d734fe76b72f coverity

merge
author Matt Johnston <matt@ucc.asn.au>
date Mon, 23 Nov 2015 23:04:48 +0800
parents c745f720ae2e
children 978887222d29
line wrap: on
line diff
--- a/cli-runopts.c	Fri Aug 07 21:26:03 2015 +0800
+++ b/cli-runopts.c	Mon Nov 23 23:04:48 2015 +0800
@@ -105,25 +105,30 @@
 void cli_getopts(int argc, char ** argv) {
 	unsigned int i, j;
 	char ** next = 0;
-	unsigned int cmdlen;
+	enum {
 #ifdef ENABLE_CLI_PUBKEY_AUTH
-	int nextiskey = 0; /* A flag if the next argument is a keyfile */
+		OPT_AUTHKEY,
 #endif
 #ifdef ENABLE_CLI_LOCALTCPFWD
-	int nextislocal = 0;
+		OPT_LOCALTCPFWD,
 #endif
 #ifdef ENABLE_CLI_REMOTETCPFWD
-	int nextisremote = 0;
+		OPT_REMOTETCPFWD,
 #endif
 #ifdef ENABLE_CLI_NETCAT
-	int nextisnetcat = 0;
+		OPT_NETCAT,
 #endif
+		/* a flag (no arg) if 'next' is NULL, a string-valued option otherwise */
+		OPT_OTHER
+	} opt;
+	unsigned int cmdlen;
 	char* dummy = NULL; /* Not used for anything real */
 
 	char* recv_window_arg = NULL;
 	char* keepalive_arg = NULL;
 	char* idle_timeout_arg = NULL;
 	char *host_arg = NULL;
+	char c;
 
 	/* see printhelp() for options */
 	cli_opts.progname = argv[0];
@@ -172,54 +177,23 @@
 
 	fill_own_user();
 
-	/* Iterate all the arguments */
 	for (i = 1; i < (unsigned int)argc; i++) {
-#ifdef ENABLE_CLI_PUBKEY_AUTH
-		if (nextiskey) {
-			/* Load a hostkey since the previous argument was "-i" */
-			loadidentityfile(argv[i], 1);
-			nextiskey = 0;
-			continue;
-		}
-#endif
-#ifdef ENABLE_CLI_REMOTETCPFWD
-		if (nextisremote) {
-			TRACE(("nextisremote true"))
-			addforward(argv[i], cli_opts.remotefwds);
-			nextisremote = 0;
-			continue;
-		}
-#endif
-#ifdef ENABLE_CLI_LOCALTCPFWD
-		if (nextislocal) {
-			TRACE(("nextislocal true"))
-			addforward(argv[i], cli_opts.localfwds);
-			nextislocal = 0;
-			continue;
-		}
-#endif
-#ifdef ENABLE_CLI_NETCAT
-		if (nextisnetcat) {
-			TRACE(("nextisnetcat true"))
-			add_netcat(argv[i]);
-			nextisnetcat = 0;
-			continue;
-		}
-#endif
-		if (next) {
-			/* The previous flag set a value to assign */
-			*next = argv[i];
-			if (*next == NULL) {
-				dropbear_exit("Invalid null argument");
+		/* Handle non-flag arguments such as hostname or commands for the remote host */
+		if (argv[i][0] != '-')
+		{
+			if (host_arg == NULL) {
+				host_arg = argv[i];
+				continue;
 			}
-			next = NULL;
-			continue;
+			/* Commands to pass to the remote host. No more flag handling,
+			commands are consumed below */
+			break;
 		}
 
-		if (argv[i][0] == '-') {
-			/* A flag *waves* */
-
-			switch (argv[i][1]) {
+		/* Begins with '-' */
+		opt = OPT_OTHER;
+		for (j = 1; (c = argv[i][j]) != '\0' && !next && opt == OPT_OTHER; j++) {
+			switch (c) {
 				case 'y': /* always accept the remote hostkey */
 					if (cli_opts.always_accept_key) {
 						/* twice means no checking at all */
@@ -232,12 +206,7 @@
 					break;
 #ifdef ENABLE_CLI_PUBKEY_AUTH
 				case 'i': /* an identityfile */
-					/* Keep scp happy when it changes "-i file" to "-ifile" */
-					if (strlen(argv[i]) > 2) {
-						loadidentityfile(&argv[i][2], 1);
-					} else  {
-						nextiskey = 1;
-					}
+					opt = OPT_AUTHKEY;
 					break;
 #endif
 				case 't': /* we want a pty */
@@ -257,7 +226,7 @@
 					break;
 #ifdef ENABLE_CLI_LOCALTCPFWD
 				case 'L':
-					nextislocal = 1;
+					opt = OPT_LOCALTCPFWD;
 					break;
 				case 'g':
 					opts.listen_fwd_all = 1;
@@ -265,12 +234,12 @@
 #endif
 #ifdef ENABLE_CLI_REMOTETCPFWD
 				case 'R':
-					nextisremote = 1;
+					opt = OPT_REMOTETCPFWD;
 					break;
 #endif
 #ifdef ENABLE_CLI_NETCAT
 				case 'B':
-					nextisnetcat = 1;
+					opt = OPT_NETCAT;
 					break;
 #endif
 #ifdef ENABLE_CLI_PROXYCMD
@@ -336,50 +305,85 @@
 				case 'b':
 					next = &dummy;
 				default:
-					fprintf(stderr, 
-						"WARNING: Ignoring unknown argument '%s'\n", argv[i]);
+					fprintf(stderr,
+						"WARNING: Ignoring unknown option -%c\n", c);
 					break;
 			} /* Switch */
-			
-			/* Now we handle args where they might be "-luser" (no spaces)*/
-			if (next && strlen(argv[i]) > 2) {
-				*next = &argv[i][2];
-				next = NULL;
-			}
+		}
 
-			continue; /* next argument */
+		if (!next && opt == OPT_OTHER) /* got a flag */
+			continue;
 
-		} else {
-			TRACE(("non-flag arg: '%s'", argv[i]))
-
-			/* Either the hostname or commands */
-
-			if (host_arg == NULL) {
-				host_arg = argv[i];
-			} else {
+		if (c == '\0') {
+			i++;
+			j = 0;
+			if (!argv[i])
+				dropbear_exit("Missing argument");
+		}
 
-				/* this is part of the commands to send - after this we
-				 * don't parse any more options, and flags are sent as the
-				 * command */
-				cmdlen = 0;
-				for (j = i; j < (unsigned int)argc; j++) {
-					cmdlen += strlen(argv[j]) + 1; /* +1 for spaces */
-				}
-				/* Allocate the space */
-				cli_opts.cmd = (char*)m_malloc(cmdlen);
-				cli_opts.cmd[0] = '\0';
+#ifdef ENABLE_CLI_PUBKEY_AUTH
+		if (opt == OPT_AUTHKEY) {
+			TRACE(("opt authkey"))
+			loadidentityfile(&argv[i][j], 1);
+		}
+		else
+#endif
+#ifdef ENABLE_CLI_REMOTETCPFWD
+		if (opt == OPT_REMOTETCPFWD) {
+			TRACE(("opt remotetcpfwd"))
+			addforward(&argv[i][j], cli_opts.remotefwds);
+		}
+		else
+#endif
+#ifdef ENABLE_CLI_LOCALTCPFWD
+		if (opt == OPT_LOCALTCPFWD) {
+			TRACE(("opt localtcpfwd"))
+			addforward(&argv[i][j], cli_opts.localfwds);
+		}
+		else
+#endif
+#ifdef ENABLE_CLI_NETCAT
+		if (opt == OPT_NETCAT) {
+			TRACE(("opt netcat"))
+			add_netcat(&argv[i][j]);
+		}
+		else
+#endif
+		if (next) {
+			/* The previous flag set a value to assign */
+			*next = &argv[i][j];
+			if (*next == NULL)
+				dropbear_exit("Invalid null argument");
+			next = NULL;
+		}
+	}
 
-				/* Append all the bits */
-				for (j = i; j < (unsigned int)argc; j++) {
-					strlcat(cli_opts.cmd, argv[j], cmdlen);
-					strlcat(cli_opts.cmd, " ", cmdlen);
-				}
-				/* It'll be null-terminated here */
+	/* Done with options/flags; now handle the hostname (which may not
+	 * start with a hyphen) and optional command */
+
+	if (host_arg == NULL) { /* missing hostname */
+		printhelp();
+		exit(EXIT_FAILURE);
+	}
+	TRACE(("host is: %s", host_arg))
 
-				/* We've eaten all the options and flags */
-				break;
-			}
+	if (i < (unsigned int)argc) {
+		/* Build the command to send */
+		cmdlen = 0;
+		for (j = i; j < (unsigned int)argc; j++)
+			cmdlen += strlen(argv[j]) + 1; /* +1 for spaces */
+
+		/* Allocate the space */
+		cli_opts.cmd = (char*)m_malloc(cmdlen);
+		cli_opts.cmd[0] = '\0';
+
+		/* Append all the bits */
+		for (j = i; j < (unsigned int)argc; j++) {
+			strlcat(cli_opts.cmd, argv[j], cmdlen);
+			strlcat(cli_opts.cmd, " ", cmdlen);
 		}
+		/* It'll be null-terminated here */
+		TRACE(("cmd is: %s", cli_opts.cmd))
 	}
 
 	/* And now a few sanity checks and setup */
@@ -388,11 +392,6 @@
 	parse_ciphers_macs();
 #endif
 
-	if (host_arg == NULL) {
-		printhelp();
-		exit(EXIT_FAILURE);
-	}
-
 #ifdef ENABLE_CLI_PROXYCMD                                                                                                                                   
 	if (cli_opts.proxycmd) {
 		/* To match the common path of m_freeing it */