cgetopt

getopt() C function not working correctly in Ubuntu 23.10


This has been driving me crazy for a while cause it was working fine before on Ubuntu until I upgraded to Ubuntu 23.10. I'm calling the getopt() function in C without any loop and only once in the program and it always scans past non-option values. I wrote a minimal reproducible issue as such

#include <stdio.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int opt = getopt(argc, (char **)argv, "hdeb:vg:wc:-");
  printf("Opt = %d, %d\n", opt, optind);
  return 0;
}

When called with program as program -d test, it prints out:

Opt = 100, 2

That looks fine because the last index where it found an option is 1.

However when I call it with as program test -d, deliberately putting the option after a non-option argument which by documentation is supposed to stop scanning at the non-option argument until I call getopt() again, it outputs:

Opt = 100, 3

The expected output is:

Opt = 100, 2

I tested further with program test test2 test3 -d, and the output was:

Opt = 100, 5

As you can see, getopt() keeps scanning past the non-option arguments like if there some kind of internal automatic loop.

I'm I missing something?? Has getopt() been redefined by new standards??


Solution

  • I'm I missing something??

    Yes.

    Has getopt() been redefined by new standards??

    No.

    What you're describing is a longstanding behavior of GNU's implementation of getopt(), which is what you will get in most Linux distributions:

    By default, getopt() permutes the contents of argv as it scans, so that eventually all the nonoptions are at the end. Two other scanning modes are also implemented. If the first character of optstring is '+' or the environment variable POSIXLY_CORRECT is set, then option processing stops as soon as a nonoption argument is encountered. [...]

    The POSIXLY_CORRECT environment variable modifies the behavior of a lot of other GNU software too, to disable GNU extensions and / or alter behavior to conform more closely to POSIX. Possibly you are used to working in an environment where that is set by default. Evidently, it is not set in the environment you are working in now.