funnyCoder
funnyCoder

Reputation: 825

How can i handle arguments in c with getopt_long

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

Answers (2)

paxdiablo
paxdiablo

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

Charlie Martin
Charlie Martin

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

Related Questions