---
 cli-runopts.c | 202 ++++++++++++++++++++++++++--------------------------------
 1 file changed, 92 insertions(+), 110 deletions(-)

diff --git a/cli-runopts.c b/cli-runopts.c
index 2b0cb7d..59ebb5a 100644
--- a/cli-runopts.c
+++ b/cli-runopts.c
@@ -105,25 +105,30 @@ static void printhelp() {
 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,58 +177,8 @@ void cli_getopts(int argc, char ** argv) {
 
        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");
-                       }
-                       next = NULL;
-                       continue;
-               }
-
-               if (argv[i][0] == '-') {
-                       /* A flag *waves* */
-                       char c = argv[i][1];
-                       if (strlen(argv[i]) != 2) {
-                               /* We only handle one flag per hyphen */
-                               fprintf(stderr, "Warning, trailing '%s' of '%s' 
is ignored.\n",
-                                       &argv[i][2], argv[i]);
-                       }
+       for (i = 1; i < (unsigned int)argc && argv[i][0] == '-'; i++) {
+               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) {
@@ -237,12 +192,7 @@ void cli_getopts(int argc, char ** argv) {
                                        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 */
@@ -262,7 +212,7 @@ void cli_getopts(int argc, char ** argv) {
                                        break;
 #ifdef ENABLE_CLI_LOCALTCPFWD
                                case 'L':
-                                       nextislocal = 1;
+                                       opt = OPT_LOCALTCPFWD;
                                        break;
                                case 'g':
                                        opts.listen_fwd_all = 1;
@@ -270,12 +220,12 @@ void cli_getopts(int argc, char ** argv) {
 #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
@@ -341,50 +291,87 @@ void cli_getopts(int argc, char ** argv) {
                                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 {
-
-                               /* 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';
-
-                               /* 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 */
-
-                               /* We've eaten all the options and flags */
-                               break;
-                       }
+               if (c == '\0') {
+                       i++;
+                       j = 0;
+                       if (!argv[i])
+                               dropbear_exit("Missing argument");
                }
+
+#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;
+               }
+               opt = OPT_OTHER;
+       }
+
+       /* Done with options/flags; now handle the hostname (which may not
+        * start with a hyphen) and optional command */
+
+       if (i >= (unsigned int)argc) { /* missing hostname */
+               printhelp();
+               exit(EXIT_FAILURE);
+       }
+       host_arg = argv[i++];
+       TRACE(("host is: %s", host_arg))
+
+       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 */
@@ -393,11 +380,6 @@ void cli_getopts(int argc, char ** argv) {
        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 */
-- 
2.6.2

Reply via email to