From 6bf3595a915111770b7a167c54ccbca86cfbec78 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 30 May 2013 16:53:16 +0200 Subject: [PATCH] Better optional argument handling. 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 tincd ignored those without a warning. Now tincd will allow optional arguments with whitespace inbetween, and will give an error when it encounters any other non-option arguments. The tinc binary now requires that all options for itself are given before the command. --- src/tincctl.c | 18 +++++------------- src/tincd.c | 12 +++++++++++- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/tincctl.c b/src/tincctl.c index fc747e75..a0061dce 100644 --- a/src/tincctl.c +++ b/src/tincctl.c @@ -79,19 +79,11 @@ static struct WSAData wsa_state; static struct option const long_options[] = { {"config", required_argument, NULL, 'c'}, - {"debug", optional_argument, NULL, 0}, - {"no-detach", no_argument, NULL, 0}, - {"mlock", no_argument, NULL, 0}, {"net", required_argument, NULL, 'n'}, {"help", no_argument, NULL, 1}, {"version", no_argument, NULL, 2}, - {"pidfile", required_argument, NULL, 5}, - {"logfile", required_argument, NULL, 0}, - {"bypass-security", no_argument, NULL, 0}, - {"chroot", no_argument, NULL, 0}, - {"user", required_argument, NULL, 0}, - {"option", required_argument, NULL, 0}, - {"force", no_argument, NULL, 6}, + {"pidfile", required_argument, NULL, 3}, + {"force", no_argument, NULL, 4}, {NULL, 0, NULL, 0} }; @@ -163,7 +155,7 @@ static bool parse_options(int argc, char **argv) { int r; int option_index = 0; - while((r = getopt_long(argc, argv, "c:n:Dd::Lo:RU:", long_options, &option_index)) != EOF) { + while((r = getopt_long(argc, argv, "+c:n:", long_options, &option_index)) != EOF) { switch (r) { case 0: /* long option */ break; @@ -185,11 +177,11 @@ static bool parse_options(int argc, char **argv) { show_version = true; break; - case 5: /* open control socket here */ + case 3: /* open control socket here */ pidfilename = xstrdup(optarg); break; - case 6: /* force */ + case 4: /* force */ force = true; break; diff --git a/src/tincd.c b/src/tincd.c index 333a207a..5f1447e6 100644 --- a/src/tincd.c +++ b/src/tincd.c @@ -167,7 +167,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 @@ -214,6 +216,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; @@ -231,6 +235,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; + } + if(!netname && (netname = getenv("NETNAME"))) netname = xstrdup(netname);