diff options
author | Lennart Poettering <lennart@poettering.net> | 2016-04-23 03:01:55 +0200 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2016-04-22 21:01:55 -0400 |
commit | 368d264387879f486593d1f3e157f5456893d889 (patch) | |
tree | ba089370f7e72b0cc1e8919f7e0a58fd51f2661e | |
parent | 07bd0e02ef6395d1a57ce948ee427300b5284aff (diff) |
machinectl: don't parse command line switches after "shell" verb (#3095)
Fixes: #2420
-rw-r--r-- | src/machine/machinectl.c | 30 |
1 files changed, 29 insertions, 1 deletions
diff --git a/src/machine/machinectl.c b/src/machine/machinectl.c index 1ce23f1c1d..b03198bbf1 100644 --- a/src/machine/machinectl.c +++ b/src/machine/machinectl.c @@ -2509,12 +2509,39 @@ static int parse_argv(int argc, char *argv[]) { {} }; + bool reorder = false; int c, r; assert(argc >= 0); assert(argv); - while ((c = getopt_long(argc, argv, "hp:als:H:M:qn:o:", options, NULL)) >= 0) + for (;;) { + const char *option_string; + + if (reorder) + option_string = "hp:als:H:M:qn:o:"; + else + option_string = "+hp:als:H:M:qn:o:"; + + c = getopt_long(argc, argv, option_string, options, NULL); + if (c < 0) { + /* We generally are fine with the fact that getopt_long() reorders the command line, and looks + * for switches after the main verb. However, for "shell" we really don't want that, since we + * want that switches passed after that are passed to the program to execute, and not processed + * by us. To make this possible, we'll first invoke getopt_long() with reordering disabled + * (i.e. with the "+" prefix in the option string), and as soon as we hit the end (i.e. the + * verb) we check if that's "shell". If it is, we exit the loop, since we don't want any + * further options processed. However, if it is anything else, we process the same argument + * again, but this time allow reordering. */ + + if (!reorder && optind < argc && !streq(argv[optind], "shell")) { + reorder = true; + optind--; + continue; + } + + break; + } switch (c) { @@ -2650,6 +2677,7 @@ static int parse_argv(int argc, char *argv[]) { default: assert_not_reached("Unhandled option"); } + } return 1; } |