0

i have a problem with parsing arguments from a program that i'm writing, the code is below:

void parse_args(int argc, char** argv)
{
    char ch;
    int index = 0;

    struct option options[] = {       
        { "help", no_argument, NULL, 'h'   },      
        { "port", required_argument, NULL, 'p'  },      
        { "stop", no_argument, NULL, 's' },         
        { 0,    0,    0,    0   }       
    };

    while ((ch = getopt_long(argc, argv, "hp:s", options, &index)) != -1) {
        switch (ch) {
            case 'h':   
                printf("Option h, or --help.\n");
                break;
            case 's':
                printf("Option s, or --stop.\n");

                break;
            case 'p':
                printf("Option p, or --port.\n");
                if (optarg != NULL)
                    printf("the port is %s\n", optarg);
                break;
            case '?':
                printf("I don't understand this option!!!\n");

            case -1:  
                break;
            default:
                printf("Help will be printed very soon -:)\n");
        }
    }
}

When i run my program i got some strange output :

./Server -p 80
Option p, or --port.
the port is 80

./Server -po 80
Option p, or --port.
the port is o

./Server -por 80
Option p, or --port.
the port is or

./Server -hoho
Option h, or --help.
Server: invalid option -- o
I don't understand this option!!!
funnyCoder
  • 787
  • 2
  • 10
  • 30
  • Why is it strange? What did you expect? – Tom Zych Sep 20 '11 at 19:45
  • 1
    the last three execution output is strange!!! – funnyCoder Sep 20 '11 at 19:50
  • 1
    No it's not. You pass `-p`, and it interprets the next thing (`o` or `or`) as the count, and ignores `80`. `p` should go after `o` and `r`. In the fourth run, it's only counting each letter once. – Tom Zych Sep 20 '11 at 20:02
  • this is not what i'm expecting!!! -por is not an option so i'm expecting an error! – funnyCoder Sep 20 '11 at 20:07
  • 3
    Oh. It accepts single-letter options folded together, like in Unix when you type `ls -ltr`. You didn't know that? Quit with the `!!!`, it's not like you're the boss of anyone here. – Tom Zych Sep 20 '11 at 20:10
  • @funnyCoder Then write your own getopt(). Or, just possibly, test your input to make sure it's a valid port number. If it's user input you definitely need to validate. – Philip Sep 20 '11 at 20:13
  • how can i prevent this strange behavior?"it's not like you're the boss of anyone here."? what you mean? – funnyCoder Sep 20 '11 at 20:14
  • @Philip : so i need to handle user input by myself! why using getopt_long? i was thinking that i was developed to parse arguments. – funnyCoder Sep 20 '11 at 20:18
  • 2
    As for getopt(), it works, but it doesn't act like you think it should. Welcome to the rest of your coding life. If you want it to change, you're going to have to do it yourself. OR you're going to have to accept a different way of parsing inputs. AND you're going to have to validate your input regardless. Trust me. – Philip Sep 20 '11 at 20:25
  • @Philip : THANKS for the great reply, i really don't understand but thanks. – funnyCoder Sep 20 '11 at 20:31

1 Answers1

8

I think the confusion stems from a misunderstanding of long get opt. Essentially it will do partial string match only when you use the -- form. When you only use - it will fallback to standard parsing so -por 80 is matched as -p or 80 (as in, the option is -p and the argument is or). Try the same thing with --po and --por. As for help, try --he or--hel

Foo Bah
  • 25,660
  • 5
  • 55
  • 79
  • Thanks it's more clear, so if i understand the only secure way to handle user input is to use something like strcmp() to validate user strings? – funnyCoder Sep 20 '11 at 20:35
  • 1
    @funnyCoder there's another call `getopt_long_only`. check that out – Foo Bah Sep 20 '11 at 23:28