Reputation: 825
i don't really understand how can i correctly handle command line arguments in c using getopt_long function, i create this code :
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
int main(int argc, char** argv) {
int next_option;
/* String of short options */
const char *short_options = "hl:k";
/* The array of long options */
const struct option long_options[] = {
{ "help", 0, NULL, 'h' },
{ "launch", 1, NULL, 'l' },
{ "kill", 0, NULL, 'k' },
{ NULL, 0, NULL, 0 }
};
do {
next_option = getopt_long(argc, argv, short_options, long_options, NULL);
switch (next_option) {
case 'h':
/* User requested help */
fprintf(stdout, "HELP\n");
break;
case 'l':
fprintf(stdout, "launching\n");
fprintf(stdout, "Want to launch on port %s\n",\
optarg);
break;
case 'k':
fprintf(stdout, "KILLING\n");
break;
case '?':
/* The user specified an invalid option */
fprintf(stdout, "Requested arg does not exist!\n");
exit(EXIT_FAILURE);
case -1:
/* Done with options */
break;
default:
/* Unexpected things */
fprintf(stdout, "I can't handle this arg!\n");
exit(EXIT_FAILURE);
}
} while(next_option != -1);
return (EXIT_SUCCESS);
}
And the output is strange, cause we can pass garbage data as command line arguments and my program don't check this errors! How can i fix that.
An example of execution :
$ ./command_line -h garbage
HELP
$ ./command_line --help garbage
HELP
$ ./command_line --launch 1200 garbage
launching
Want to launch on port 1200
$ ./command_line --lBADARG 1200
command_line: unrecognized option `--lBADARG'
Requested arg does not exist!
$ ./command_line -lBADARG 1200
launching
Want to launch on port BADARG
Thanks for your help.
Upvotes: 1
Views: 892
Reputation: 881323
The reason the garbage
is getting through okay is because getopt
and its brethren are for processing options, not all command lne arguments. Not all arguments are options.
The reason that --lBADARG
is treated differently to -lBADARG
is because of the way it wants to handle them. --lBADARG
is an option lBADARG
with no parameters while -lBADARG
is the -l
option with a parameter of BADARG
. The former is not listed as a valid option but the latter is.
And the final possible issue is that BADARG
is being treated as a port. That's because the getopt
stuff neither knows nor cares about parameter types, that's up to your code. If you want to ensure it's numeric, you should check for that. It may well be that you want to support symbolic port names (looked up in /etc/ports
for example).
Upvotes: 0
Reputation: 112366
Okay, what's happening is this:
in this case:
$ ./command_line --lBADARG 1200
command_line: unrecognized option `--lBADARG'
Requested arg does not exist!
by giving it --lBADARG
you're saying look for the LONG argument lBADARG
, and you don't have one.
in this case:
$ ./command_line -lBADARG 1200
launching
Want to launch on port BADARG
you're successfully telling it to use the -l
flag which has an argument. It behaves as expected, telling you that argument is BADARG
.
If you try
$ ./command_line -l 1200
or
$ ./command_line -l1200
or
$ ./command_line --launch 1200
that should do what you expect. And if you want to get the arguments that are not options, you'll find them in the argv vector after you've done the getopt processing, because getopt_long conveniently permutes the argv vector to leave non-option arguments there.
Upvotes: 2