clinuxgetopt-longoptionparser

C: getopt_long() always returns invalid option


I'm trying to add a new option to an already working C program using getopt_long. The option I want to add is -S but every time I try to run the code I get:

./HidCom: invalid option --'S'

I simply add a new element to long_options vector concerning the option I want to add in this way:

    {"Status",  required_argument, 0, 'S'},

Below there is my code:

#include <stdlib.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <asm/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/hiddev.h>
#include <linux/input.h>
#include <time.h>
#include <ctype.h>
#include <getopt.h>
#include <string.h>


int main (int argc, char **argv) {
    int n=64,d=0,info=0,increment=0,p=0,vid=0x16c0,pid=0x05df,q=0,f=1,ctrl=0,r=1,c,i,j;
    int inputState = 0;
    char path[256],buf[256];
    path[0]=0;
    for(i=0;i<256;i++) buf[i]=0;
    //opterr = 0; in order to show the error
    int option_index = 0;
    struct option long_options[] =
    {
        {"control", no_argument,      &ctrl,1},
        {"c",       no_argument,      &ctrl,1},
        {"delay",   required_argument, 0, 'd'},
        {"d",       required_argument, 0, 'd'},
        {"feature", no_argument,         &f,1},
        {"f",       no_argument,         &f,1},
        {"help",    no_argument,       0, 'h'},
        {"i",       no_argument,      &info,1},
        {"info",    no_argument,      &info,1},
        {"increment",no_argument,&increment,1},
        {"I",       no_argument, &increment,1},
        {"path",    required_argument, 0, 'P'},
        {"pid",     required_argument, 0, 'p'},
        {"quiet",   no_argument,        &q, 1},
        {"q",       no_argument,        &q, 1},
        {"repeat",  required_argument, 0, 'r'},
        {"size",    required_argument, 0, 's'},
        {"Status",  required_argument, 0, 'S'},
        {"vid",     required_argument, 0, 'v'},
        {0, 0, 0, 0}
    };
    while ((c = getopt_long (argc, argv, "cd:fhiIp:qv:r:s:",long_options,&option_index)) != -1)
     switch (c)
        {
        case 'h':
        printf("hid_test [options] [data]\
        // prints help 
        exit(1);
        break;
        case 'c':   //control endpoint
             ctrl=1;
             break;
        case 'd':   //delay
            d = atoi(optarg);
            break;
        case 'f':   //feature report
            f=1;
            break;
        case 'i':   //info
            info=1;
            break;
        case 'I':   //increment
            increment=1;
            break;
        case 'p':   //pid
            sscanf(optarg, "%x", &pid);
            break;
        case 'P':   //path
            strncpy(path,optarg,256);
            break;
        case 'q':   //quiet
            q=1;
            break;
        case 'r':   //repeat
            r = atoi(optarg);
            break;
        case 's':   //report size
            n = atoi(optarg);   //No always add report index
            break;
        case 'S':
            inputState = 1;
            n = atoi(optarg);
            break;
        case 'v':   //vid
            sscanf(optarg, "%x", &vid);
            break;
        case '?':
            fprintf (stderr, "Unknown option character 0x%02x (%c)\n",optopt,optopt);
            return 1;
        default:
         //abort ();
        break;
        }

I tried also different char, but I get always the invalid option. Where is the issue?


Solution

  • If you want an option to have a single-character version, it needs to go in the third argument to getopt_long(), not just in the long option array:

    getopt_long (argc, argv, "cd:fhiIp:qv:r:s:S:",long_options,&option_index)
    

    The val field of the struct option is just used to tell getopt_long() what to return when it encounters that long option; it doesn't define a short option.