Parsing command line options with multiple arguments [getopt?]

19,764

Your code was actually very, very close to working. The only thing you were missing is that getopt only expects you to consume one argument after -l, and therefore continues command line parsing following the first argument to -l. Since you're going behind its back and pulling off more arguments, you have to tell getopt where to start parsing the command line again.

getopt stores that information in the global variable optind. When I added the line:

optind = index - 1;

before the break; in your l case, your code started working.

Share:
19,764
Salamander
Author by

Salamander

Updated on June 05, 2022

Comments

  • Salamander
    Salamander about 2 years

    I need my program to get several arguments from command line, the syntax is as follows:

    getpwd -l user1 user2 ... -L -X -S...
    

    So, I need to get the users behind the -l option. I tried using getopt, but without much luck, it only works when I place the other options before the -l:

    getpwd -L -X -S ... -l user1 user2 ...
    

    My code (for -l and -S):

        while((c = getopt(argc, argv, "l:S")) != -1){
        switch(c){
            case 'l':
                index = optind-1;
                while(index < argc){
                    next = strdup(argv[index]); /* get login */
                    index++;
                    if(next[0] != '-'){         /* check if optarg is next switch */
                        login[lcount++] = next;
                    }
                    else break;
                }
                break;
            case 'S':
                sflag++;                        /* other option */
                break;
            case ':':                           /* error - missing operand */
                fprintf(stderr, "Option -%c requires an operand\n", optopt);
                break;
            case '?':                           /* error - unknown option */
                fprintf(stderr,"Unrecognized option: -%c\n", optopt);
                break;
          }
       }
    

    optopt and optind are extern int.

    So, the question is: Can I use the getopt() function (or getopt_long()) ? Or do I have to write my own parser to get what I need ?

  • Salamander
    Salamander over 11 years
    For some reason optind = index-1 works for me ... I will do look at it more closely tomorrow. But thanks so much. I am amazed this works ... I found everywhere that getopts() can't be used this way :D
  • rra
    rra over 11 years
    Apologies, you are entirely correct, it should be optind - 1. A flaw in my testing; I forgot to test that the following option was properly parsed. I'll fix that.