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 aaad1da681e4bb7056d5ed1a0fb28158d4721044..7416d11bb0c25d1b9edbfa7722125a2d84a1078b 100644 (file)
@@ -178,7 +178,9 @@ static bool parse_options(int argc, char **argv) {
                                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
@@ -187,6 +189,8 @@ static bool parse_options(int argc, char **argv) {
 
                        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;
@@ -225,8 +229,7 @@ static bool parse_options(int argc, char **argv) {
 
                        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 */
@@ -237,6 +240,8 @@ static bool parse_options(int argc, char **argv) {
                                break;
 
                        case 'K':                               /* generate public/private keypair */
+                               if(!optarg && optind < argc && *argv[optind] != '-')
+                                       optarg = argv[optind++];
                                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;
+                               if(!optarg && optind < argc && *argv[optind] != '-')
+                                       optarg = argv[optind++];
                                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;
 }