Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getopt value stays null

Tags:

c

getopt

I am passing my program inputs and I could see them in argv but getopt doesnt seem to have the argument that I expect.

This is how I run my prog: ./my_prog -X -f filename

<snip>
while ((opt = getopt(argc, argv, "Xf:eE:dD")) != EOF) {
    switch (opt) {
       case 'X':
       case 'f':
                if (optarg == NULL)
                fput("no point of living", fp);         << for debugging

</snip>

I always get optarg as null. WHY?

like image 230
hari Avatar asked Jun 23 '11 06:06

hari


People also ask

Can Optarg be null?

When the option has no argument, the value in optarg is a null pointer. This is how you can tell whether an optional argument was supplied.

What does getopt return?

RETURN VALUE The getopt() function returns the next option character specified on the command line. A colon (:) is returned if getopt() detects a missing argument and the first character of optstring was a colon (:).

What do the colons mean in getopt?

An option character in this string can be followed by a colon (' : ') to indicate that it takes a required argument. If an option character is followed by two colons (' :: '), its argument is optional; this is a GNU extension. getopt has three ways to deal with options that follow non-options argv elements.

What is argc in getopt?

The getopt() function parses the command-line arguments. Its arguments argc and argv are the argument count and array as passed to the main() function on program invocation.


1 Answers

I just dealt with this issue, and it appears this question was never fully answered.

You have to make sure you're setting the external libc variable opterr = 0 before you call getopt; if you don't reset it and getopt previously had an error in another application anywhere in your system that used it, it will fail for the argument. I'll also reiterate the existing point that because you don't have a break statement after case 'X': that's a sure sign of an issue since it will fall through.

getopt only processes one argument at a time, so falling through case X into case f is a bad thing to do. You should always have a break in each case statement of a switch unless you are absolutely certain it should fall through (which is very rare in my experience). As another bit of general good practice, you should always enclose blocks of code in { } (referring to your conditional) unless it's a return statement or break or something that causes the program flow to to drop out of the current or parent block scope or to enter a new scope through a function or method call.

I think your option string Xf:eE:dD is fine. This indicates that:

1) The following will simply be option flags that always have a null argument: XedD

2) The following options will require an argument: fE

If this is the functionality you're looking for, the given option string is fine. If you're using GNU libc, per the other above answer, you can use :: after an option in the option string to indicate that the option might have an argument, but doesn't have to.

So at the top of your file make sure you at least have:

extern int opterr;

Then right before you call getopt for the first time in your code, set opterr to 0.

e.g.

opterr = 0;

while ((opt = getopt(argc, argv, "Xf:eE:dD")) != EOF) {
    switch (opt) {
       case 'X':
       case 'f':
                if (optarg == NULL)
                fput("no point of living", fp);         << for debugging

This should at least partially resolve your issue. Here's a link to an example:

http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html

Cheers,

Jon

like image 163
jhyry Avatar answered Oct 20 '22 12:10

jhyry