16

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 ?

2
  • 1
    If you are okay with one user per -l, you can just let the user use as many -l options as needed. Commented Mar 17, 2013 at 22:32
  • sadly, the specification for the program says it has to work with multiple users per -l Commented Mar 17, 2013 at 22:53

3 Answers 3

16

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.

Sign up to request clarification or add additional context in comments.

2 Comments

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
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.
0

I wrote a C library(GPL license) for parsing command line arguments:

https://github.com/Vincenzo1968/myoptParser

https://github.com/Vincenzo1968/myoptParser/blob/master/how_to_use.md

You can specify the minimum and the maximum number of arguments that option accepts. You can also specify that an option takes zero or more arguments (or one or more, two or more, and so on). And, of course, you can specify a fixed number of arguments: zero, one, two, and so on.

You can also specify the type of the arguments: string, integer or float. The parser checks that the number and type specified matches and, otherwise, it returns an error.

The parser also allows you to specify whether an option is required or not. You can finally specify the mutually exclusive options.

Comments

0

The following function will generate an argc, argv pair for a single option within an argument list:

void GetArgsList (int argc, char *argv[], int* o_argc, char*** o_argv)
{
    char** ret = NULL;
    int i;
    int count = 0;

    for (i = optind - 1; i < argc ; ++i)
    {
        if (argv[i][0]=='-')
        {
            break;
        }
        else
        {
            if (NULL == ret)
            {
                ret = &argv[i];
            }
            count++;
        }
    }

    optind = i - 1;

    if (o_argc)
    {
        *o_argc = count;
    }

    *o_argv = ret;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.