What it the correct usage if I want this behaviour:
$ ./a.out --help for printing help information
$ ./a.out --version for printing the program version
I managed to code this so that it takes the arguments but I don't know a good / correct way to separate the messages since they are the same case.
static struct option long_options[] = {
{"help", no_argument, 0, 0 },
{"version", no_argument, 0, 0 },
{0, 0, 0, 0 }
};
int main(int argc, char *argv[]) {
while (1) {
int this_option_optind = optind ? optind : 1;
int option_index = 0;
c = getopt_long(argc, argv, "",
long_options, &option_index);
if (c == -1)
break;
switch (c) {
case 0:
printf("option %s", long_options[option_index].name);
if (optarg)
printf(" with arg %s", optarg);
printf("\n");
return 0;
case '0':
case '1':
case '2':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf("option 2 2 %c\n", c);
return 0;
case 'a':
printf("option a\n");
break;
case 'b':
printf("option b\n");
break;
case 'c':
printf("option c with value '%s'\n", optarg);
break;
case 'd':
printf("option d with value '%s'\n", optarg);
break;
case '?':
break;
default:
printf("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc) {
printf("non-option ARGV-elements: ");
while (optind < argc)
printf("%s ", argv[optind++]);
printf("\n");
}
...
Here you have an example:
while (1)
{
int option_index = 0;
static struct option long_options[] = {
{"with_param", required_argument, 0, 'p'},
{"version", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{0, 0, 0, 0}
};
option = getopt_long(argc, argv, "p:vh",
long_options, &option_index);
if (option == -1)
break;
switch (option) {
case 'p':
{
store_parameter(optarg);
break;
}
case 'v':
{
print_version();
break;
}
case 'h':
{
print_help();
exit(EXIT_SUCCESS);
break;
}
default:
{
fprintf(stderr, "Error (%s): unrecognized option.\n", __FUNCTION__);
print_help();
exit(EXIT_FAILURE);
break;
}
} /* end switch */
}
Notice the string "p:vh" as parameter of getopt_long, which allows you to also use short options. (":" follows options with a required argument)
You need to tell getopt_long the values it has to return:
static struct option long_options[] = {
{"help", no_argument, NULL, 1 },
{"version", no_argument, NULL, 2 },
{0, 0, 0, 0 }
};
Also, you could use "-h" as a synonym to "--help" and "-V" as a synonym to "--version", this would be done this way:
static struct option long_options[] = {
{"help", no_argument, NULL, 'h' },
{"version", no_argument, NULL, 'V' },
{0, 0, 0, 0 }
};
/* ... */
c = getopt_long(argc, argv, "abc:d:Vh", long_options, &option_index);
/* ... */
case 'h': // instead of case 1:
/* ... */
case 'V': // instead of case 2:
/* ...*/
Related
In the getopt_long example here, why are the short options separated by a colon at abc:d:f: and why are abc are grouped together like that?
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
/* Flag set by ‘--verbose’. */
static int verbose_flag;
int
main (int argc, char **argv)
{
int c;
while (1)
{
static struct option long_options[] =
{
/* These options set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
{"brief", no_argument, &verbose_flag, 0},
/* These options don’t set a flag.
We distinguish them by their indices. */
{"add", no_argument, 0, 'a'},
{"append", no_argument, 0, 'b'},
{"delete", required_argument, 0, 'd'},
{"create", required_argument, 0, 'c'},
{"file", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long (argc, argv, "abc:d:f:",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'a':
puts ("option -a\n");
break;
case 'b':
puts ("option -b\n");
break;
case 'c':
printf ("option -c with value `%s'\n", optarg);
break;
case 'd':
printf ("option -d with value `%s'\n", optarg);
break;
case 'f':
printf ("option -f with value `%s'\n", optarg);
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
On GNU's page, it is said that
An option character in this string can be followed by a colon (:) to
indicate that it takes a required argument.
For example, xy:zq accepts the options x, y, z, q; y requires an additional argument.
I would like to use getopt_long() correctly and am trying to understand why certain choices were made in the example of getopt_long. (I've copied the full code listing below).
I understand that case 0 occurs when the flag field of the struct is not null (find getopt_long returns 0), but why does the example show retesting long_options[option_index].flag for null in case 0? Isn't this guaranteed given that we are in case 0?
Asked another way: What input could I provide to cause the code to enter case 0 but fail the first if-statement within it? Is printf ("option %s", long_options[option_index].name); unreachable?
25.2.4 Example of Parsing Long Options with getopt_long
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
/* Flag set by ‘--verbose’. */
static int verbose_flag;
int
main (int argc, char **argv)
{
int c;
while (1)
{
static struct option long_options[] =
{
/* These options set a flag. */
{"verbose", no_argument, &verbose_flag, 1},
{"brief", no_argument, &verbose_flag, 0},
/* These options don’t set a flag.
We distinguish them by their indices. */
{"add", no_argument, 0, 'a'},
{"append", no_argument, 0, 'b'},
{"delete", required_argument, 0, 'd'},
{"create", required_argument, 0, 'c'},
{"file", required_argument, 0, 'f'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long (argc, argv, "abc:d:f:", long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'a':
puts ("option -a\n");
break;
case 'b':
puts ("option -b\n");
break;
case 'c':
printf ("option -c with value `%s'\n", optarg);
break;
case 'd':
printf ("option -d with value `%s'\n", optarg);
break;
case 'f':
printf ("option -f with value `%s'\n", optarg);
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
/* Instead of reporting ‘--verbose’
and ‘--brief’ as they are encountered,
we report the final status resulting from them. */
if (verbose_flag)
puts ("verbose flag is set");
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
exit (0);
}
I am new to c programming using command line arguments so despite finding few simmilar posts I am still stuck on this problem.
I need to pass a command line option that have more than 1 argument, for example
./testProgram --command arg1 arg2 arg3
here is my code
static struct option long_options[] = {
{"rdonly", required_argument, 0, 'a'},
{"wronly", required_argument, 0, 'b'},
{"command", required_argument, 0, 'c'},
{"verbose", no_argument, 0, 'd'},
{0,0,0,0}
};
c=getopt_long(argc,argv, "", long_options, &option_index);
if(c == -1)
break;
switch(c) {
case 'a':
rdonly(fd,optarg);
break;
case 'b':
wronly(fd,optarg);
break;
case 'c':
command(optind,optarg,argc,argv);
break;
case 'd':
printf("its verbose\n");
break;
default:
printf("WRONG OPTION\n");
}
}
//command function
int command(int optind, char *optarg, int argc, char* argv)
{
printf("Its option command with argument %s\n",optarg);
return 0;
}
I'm having problems getting my command-line arguments to work properly. The arguments appear to fail when the argc is higher than 3 and after that you can only get them to work if you write -fwhatever and not -f whatever as it should be. -t also copies the value of -o.
int main(int argc,char **argv)
{
int c;
/* Are we in root? */
if(geteuid() !=0)
{
printf("Root access is required to run this program. \n");
exit(0);
}
/* How do we use the program */
if ((argc < 6) || (argc > 8))
{
usage(argv[0]);
exit (0);
}
while (1)
{
static struct option long_options[] =
{
/* Options */
{"send", no_argument, 0, 's'},
{"recieve", no_argument, 0, 'r'},
{"file", required_argument, 0, 'f'},
{"data", required_argument, 0, 'd'},
{"destip", required_argument, 0, 'i'},
{"destport", required_argument, 0, 'p'},
{"sourceip", required_argument, 0, 'o'},
{"sourceport", required_argument, 0, 't'},
{0, 0, 0, 0}
};
int option_index = 0;
c = getopt_long (argc, argv, "srf:d:i:p:o:t:",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 's':
puts ("option -s\n");
break;
case 'r':
puts ("option -r\n");
break;
case 'f':
printf ("option -f with value `%s'\n", optarg);
break;
case 'd':
printf ("option -d with value `%s'\n", optarg);
break;
case 'i':
printf ("option -i with value `%s'\n", optarg);
break;
case 'p':
printf ("option -p with value `%s'\n", optarg);
break;
case 'o':
printf ("option -o with value `%s'\n", optarg);
case 't':
printf ("option -t with value `%s'\n", optarg);
case '?':
/* Error message printed */
break;
default:
abort ();
}
}
/* Print any remaining command line arguments (not options). */
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
putchar ('\n');
}
getchar ();
exit (0);
}
There's obviously something horribly wrong here, but it can't seem to find it.
Regarding the -o copied to -t, you forgot to put a break; at the end of the case.
Also, I would have removed the argc checking. Let getopt do its magic. You can check at the end of parsing if all mandatory options were set. You can also check for unknown arguments.
I'm trying to use the getopt_long() function for the first time only I'm having problems with arguments that aren't flags. For instance, in my code when a unknown argument is given I want to use it as a input file. When I run this with only a file name it is not printed, if I first use a flag, any flag, then I can print it.
How can I fix this?
#include <stdio.h>
#include <getopt.h>
static struct option long_options[] = {
{"help", no_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{"algorithm", required_argument, 0, 'a'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[]) {
int c;
int option_index = 0;
while(42) {
c = getopt_long(argc, argv, "hi:o:a:", long_options,
&option_index);
if(c == -1)
break;
switch(c) {
case 'h': /* --help */
printf("--help flag\n");
break;
case 'i': /* --input */
printf("--input flag\n");
break;
case 'o': /* --output */
printf("--output flag\n");
break;
case 'a': /* --algorithm */
printf("--algorithm flag \n");
break;
default: /* ??? */
fprintf(stderr, "Invalid option");
return 1;
}
if(optind < argc) {
printf("other arguments: ");
while(optind < argc) {
printf ("%s ", argv[optind]);
optind++;
}
printf("\n");
}
}
return 0;
}
The loop should only contain the switch. Process the residual arguments in a separate (not nested) loop:
#include <stdio.h>
#include <getopt.h>
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{"algorithm", required_argument, 0, 'a'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[])
{
int opt;
int option_index = 0;
int i;
while ((opt = getopt_long(argc, argv, "hi:o:a:", long_options, &option_index)) != -1)
{
switch(opt)
{
case 'h': /* --help */
printf("--help flag\n");
break;
case 'i': /* --input */
printf("--input flag (%s)\n", optarg);
break;
case 'o': /* --output */
printf("--output flag (%s)\n", optarg);
break;
case 'a': /* --algorithm */
printf("--algorithm flag (%s)\n", optarg);
break;
default: /* ??? */
fprintf(stderr, "Invalid option %c\n", opt);
return 1;
}
}
for (i = optind; i < argc; i++)
printf("Process: %s\n", argv[i]);
return 0;
}
There is a way to have GNU getopt() and getopt_long() return file name arguments as if they were options with the 'letter' ^A '\1'; use '-' as the first character of the short options string, and trap '\1' in the switch; the value of optarg is the name of the file.
#include <stdio.h>
#include <getopt.h>
static struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"input", required_argument, 0, 'i'},
{"output", required_argument, 0, 'o'},
{"algorithm", required_argument, 0, 'a'},
{0, 0, 0, 0}
};
int main(int argc, char *argv[])
{
int opt;
int option_index = 0;
int i;
while ((opt = getopt_long(argc, argv, "-hi:o:a:", long_options, &option_index)) != -1)
{
switch(opt)
{
case 'h': /* --help */
printf("--help flag\n");
break;
case 'i': /* --input */
printf("--input flag (%s)\n", optarg);
break;
case 'o': /* --output */
printf("--output flag (%s)\n", optarg);
break;
case 'a': /* --algorithm */
printf("--algorithm flag (%s)\n", optarg);
break;
case '\1':
printf("File: %s\n", optarg);
break;
default: /* ??? */
fprintf(stderr, "Invalid option %c\n", opt);
return 1;
}
}
for (i = optind; i < argc; i++)
printf("Process: %s\n", argv[i]);
return 0;
}
However, you do need the loop after the argument processing loop in case your cantankerous user types:
program -- abc def
The '--' terminates the while() loop without processing the file name arguments.
It doesn't work because you break out of the outer while loop when getopt_long returns -1 (which indicates that there are no more options).
You need to move the if (optind < argc) block out of the outer while loop; it doesn't belong there anyway. This might be clearer if you wrote that outer while loop as:
while ((c = getopt_long(...)) != -1)
{
switch (c)
{
/* Deal with flags. */
}
}