Better optional argument handling.
authorGuus Sliepen <guus@tinc-vpn.org>
Thu, 30 May 2013 14:43:20 +0000 (16:43 +0200)
committerGuus Sliepen <guus@tinc-vpn.org>
Thu, 30 May 2013 14:43:20 +0000 (16:43 +0200)
Some options can take an optional argument. However, in this case GNU getopt
requires that the optional argument is right next to the option without
whitespace inbetween. If there is whitespace, getopt will treat it as a
non-option argument, but tinc ignored those without a warning. Now tinc will
allow optional arguments with whitespace inbetween, and will give an error when
it encounters any other non-option arguments.

src/tincd.c

index aaad1da..7416d11 100644 (file)
@@ -178,7 +178,9 @@ static bool parse_options(int argc, char **argv) {
                                break;
 #endif
 
                                break;
 #endif
 
-                       case 'd':                               /* inc debug level */
+                       case 'd':                               /* increase debug level */
+                               if(!optarg && optind < argc && *argv[optind] != '-')
+                                       optarg = argv[optind++];
                                if(optarg)
                                        debug_level = atoi(optarg);
                                else
                                if(optarg)
                                        debug_level = atoi(optarg);
                                else
@@ -187,6 +189,8 @@ static bool parse_options(int argc, char **argv) {
 
                        case 'k':                               /* kill old tincds */
 #ifndef HAVE_MINGW
 
                        case 'k':                               /* kill old tincds */
 #ifndef HAVE_MINGW
+                               if(!optarg && optind < argc && *argv[optind] != '-')
+                                       optarg = argv[optind++];
                                if(optarg) {
                                        if(!strcasecmp(optarg, "HUP"))
                                                kill_tincd = SIGHUP;
                                if(optarg) {
                                        if(!strcasecmp(optarg, "HUP"))
                                                kill_tincd = SIGHUP;
@@ -225,8 +229,7 @@ static bool parse_options(int argc, char **argv) {
 
                        case 'n':                               /* net name given */
                                /* netname "." is special: a "top-level name" */
 
                        case 'n':                               /* net name given */
                                /* netname "." is special: a "top-level name" */
-                               netname = strcmp(optarg, ".") != 0 ?
-                                               xstrdup(optarg) : NULL;
+                               netname = strcmp(optarg, ".") != 0 ? xstrdup(optarg) : NULL;
                                break;
 
                        case 'o':                               /* option */
                                break;
 
                        case 'o':                               /* option */
@@ -237,6 +240,8 @@ static bool parse_options(int argc, char **argv) {
                                break;
 
                        case 'K':                               /* generate public/private keypair */
                                break;
 
                        case 'K':                               /* generate public/private keypair */
+                               if(!optarg && optind < argc && *argv[optind] != '-')
+                                       optarg = argv[optind++];
                                if(optarg) {
                                        generate_keys = atoi(optarg);
 
                                if(optarg) {
                                        generate_keys = atoi(optarg);
 
@@ -274,6 +279,8 @@ static bool parse_options(int argc, char **argv) {
 
                        case 4:                                 /* write log entries to a file */
                                use_logfile = true;
 
                        case 4:                                 /* write log entries to a file */
                                use_logfile = true;
+                               if(!optarg && optind < argc && *argv[optind] != '-')
+                                       optarg = argv[optind++];
                                if(optarg)
                                        logfilename = xstrdup(optarg);
                                break;
                                if(optarg)
                                        logfilename = xstrdup(optarg);
                                break;
@@ -291,6 +298,12 @@ static bool parse_options(int argc, char **argv) {
                }
        }
 
                }
        }
 
+       if(optind < argc) {
+               fprintf(stderr, "%s: unrecognized argument '%s'\n", argv[0], argv[optind]);
+               usage(true);
+               return false;
+       }
+
        return true;
 }
 
        return true;
 }