getopt_long(3) doesn't return longopt index when short option is supplied

Issue #105 new
Takehiko NOZAKI repo owner created an issue

getopt_long(3) is completely broken, if getopt_long(3) found short option like -f(not --foo), it uses normal getopt(3) and never use long option. so that it desn't update index of longopts(=getopt_long(3)'s 5th argument).

following is minimal test case

$ cat >test.c
#include <getopt.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

static const char *optstr = "f";
static struct option longopts[] = {
        { "foo", no_argument, NULL, 'f' },
        { NULL, 0, NULL, 0 }
};
int
main(int argc, char **argv)
{
        int ch, idx;
        while ((ch = getopt_long(argc, argv, optstr, longopts, &idx)) != -1) {
                switch (ch) {
                case 'f':
                        printf("--%s or -%c found!\n", longopts[idx].name, ch);
                        break;
                default:
                        printf("unknown argument\n");
                        abort();
                }
        }
        exit(EXIT_SUCCESS);
}
^D
$ make test
$./ test -f
Memory fault (core dumped)

Comments (2)

  1. Takehiko NOZAKI reporter

    OpenBSD's getopt_long(3) seems fine(but seems many warning build under NetBSD). i'll take it later.

  2. Takehiko NOZAKI reporter

    replacing OpenBSD's getopt(3) + getopt_long(3) cause compatibility problem. following won't work as you expected:

    while ((ch = getopt(argc, argv, "-abc")) != -1) {
        switch (ch) {
        case '-':
            ...
    }
    

    you have to rewrite program with GNU getopt semantics:

    while ((ch = getopt(argc, argv, "abc-")) != -1) {
        switch (ch) {
        case '-':
            ...
    }
    
  3. Log in to comment