I want to get options for this command:
my_cmd show --value true -D
To get that, I need to go through the options twice (due to architecture). During the second pass, it is impossible to retrieve correctly the argument corresponding to its option.
In this example, during the second pass the argument retrieved (for option --value) is -D instead of true.
First pass:
void getoptions (int argc, char **argv, globalargs_t* globalargs) {
static const char *optstring = "vDqnd:c:f:o:h?:";
static const struct option longopts[] = {
{ "help", no_argument, NULL, 'h' },
{ "Debug", no_argument, NULL, 'D'},
{ "verbose", no_argument, NULL, 'v'},
{ "quiet", no_argument, NULL, 'q'},
{ "noheader", no_argument, NULL, 0},
{ "delimiter", required_argument, NULL, 0},
{ "columns", required_argument, NULL, 0},
{ "filter", required_argument, NULL, 0},
{ "order", required_argument, NULL, 0},
{ "getid", no_argument, NULL, 'i'},
{ NULL, no_argument, NULL, 0 }
};
int opt = 0;
int longindex = 0;
//opterr = 0;
/* Process the arguments with getopt_long(), then populate globalargs-> */
opt = getopt_long( argc, argv, optstring, longopts, &longindex );
while( opt != -1 ) {
switch( opt ) {
case '?':
break;
case 'D':
globalargs->debug = 1; /* true */
break;
case 'v':
globalargs->verbose++;
break;
case 'q':
globalargs->quiet = 1;
break;
case 'i':
globalargs->id = 1;
break;
case 'h':
globalargs->help = 1;
break;
case 0: /* long option without a short arg */
if( strcmp( "Debug", longopts[longindex].name ) == 0 ) {
globalargs->debug = 1;
}
if( strcmp( "verbose", longopts[longindex].name ) == 0 ) {
globalargs->verbose = 1;
}
if( strcmp( "quiet", longopts[longindex].name ) == 0 ) {
globalargs->quiet = 1;
}
if( strcmp( "noheader", longopts[longindex].name ) == 0 ) {
globalargs->noheader = 1;
}
if( strcmp( "delimiter", longopts[longindex].name ) == 0 ) {
globalargs->delimiter = *optarg;
}
if( strcmp( "filter", longopts[longindex].name ) == 0 ) {
globalargs->filter = optarg;
}
if( strcmp( "order", longopts[longindex].name ) == 0 ) {
globalargs->order = optarg;
}
if( strcmp( "columns", longopts[longindex].name ) == 0 ) {
globalargs->columns = optarg;
}
break;
default:
/* You won't actually get here. */
break;
}
opt = getopt_long( argc, argv, optstring, longopts, &longindex );
}
if (optind < argc) {
while (optind < argc) {
globalargs->actions[globalargs->actionsindex] = argv[optind++];
globalargs->actionsindex++;
}
}
}
Second pass :
void getspecificoptions(int argc, char **argv, globalargs_t* globalargs) {
static const char *optstring = ":n:d:v:d";
static const struct option longopts[] = {
{ "name", required_argument, NULL, 'n'},
{ "domain", required_argument, NULL, 0},
{ "value", required_argument, NULL, 0},
{ "defined_value", required_argument, NULL, 0},
{ NULL, no_argument, NULL, 0 }
};
optind = 1;
int opt = 0;
int longindex = 0;
/* Process the arguments with getopt_long(), then populate globalargs-> */
opt = getopt_long( argc, argv, optstring, longopts, &longindex );
while( opt != -1 ) {
switch( opt ) {
case 'n':
/* If used in update/add => must be still a filter */
globalargs->filter = strcat(globalargs->filter,"cluster.name=");
globalargs->filter = strcat(globalargs->filter, optarg);
if(!globalargs->table || strcmp(globalargs->table, "cluster") == 0 ) {
globalargs->table = "cluster";
}
else {
clmError(&t, "dbm-command", -1, "Incompatible options.");
exit(EXIT_FAILURE_OPTIONS);
}
break;
case 0: /* long option without a short arg */
if( strcmp( "domain", longopts[longindex].name ) == 0 ) {
}
else {
char* f = my_new(500*sizeof(char));
f = strcat(f, "cluster.dns_domain=");
f = strcat(f, optarg);
globalargs->actions[globalargs->actionsindex] = f;
globalargs->actionsindex++;
}
if(strcmp(globalargs->table,"") == 0 || strcmp(globalargs->table, "cluster") == 0 ) {
globalargs->table = "cluster";
}
else {
clmError(&t, "dbm-command", -1, "Incompatible options.");
exit(EXIT_FAILURE_OPTIONS);
}
}
if( strcmp( "value", longopts[longindex].name ) == 0 ) {
if(strcmp(globalargs->actions[0], "show") == 0 || strcmp(globalargs->actions[0], "delete") == 0 ) {
globalargs->filter = realloc(globalargs->filter, strlen(globalargs->filter) + strlen(optarg) + strlen("cluster_profile.value=") + 1);
globalargs->filter = strcat(globalargs->filter,"cluster_profile.value=");
globalargs->filter = strcat(globalargs->filter, optarg);
}
else {
char* act = my_new(strlen(optarg) + strlen("cluster_profile.value=") + 1U);
act = strcat(act, "cluster_profile.value=");
act = strcat(act, optarg);
globalargs->actions[globalargs->actionsindex] = act;
globalargs->actionsindex++;
}
if(strcmp(globalargs->table,"") == 0 || strcmp(globalargs->table, "profile") == 0 ) {
globalargs->table = "profile";
}
else {
clmError(&t, "dbm-command", -1, "Incompatible options.");
exit(EXIT_FAILURE_OPTIONS);
}
}
if( strcmp( "defined_value", longopts[longindex].name ) == 0 ) {
/* If used in update/add => must be still a filter */
globalargs->filter = strcat(globalargs->filter,"cluster_profile.defined_value=");
globalargs->filter = strcat(globalargs->filter, optarg);
if(!globalargs->table || strcmp(globalargs->table, "profile") == 0 ) {
globalargs->table = "profile";
}
else {
clmError(&t, "dbm-command", -1, "Incompatible options.");
exit(EXIT_FAILURE_OPTIONS);
}
}
break;
}
opt = getopt_long( argc, argv, optstring, longopts, &longindex );
}
}
After these passes I have globalargs->filter="-D".
Any help would be appreciated.
Thank you!
optind must be reset to 0 instead of 1. The first time through, the qualification flags are parsed, but the second time they are not, because optind is 1 and not 0. Setting it to 0 reparses the string.
The first character of the optstring must also be + or – (before the leading colon) to prevent the arguments from being reordered.
This is all under the assumption that you are using GNU’s getopt_long.