Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iio_utils: rework/fix command line argument parsing #538

Merged
merged 1 commit into from
Jun 4, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions tests/iio_adi_xflow_check.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,13 @@ static void *monitor_thread_fn(void *data)
return (void *)0;
}

#define MY_OPTS "s:a"

int main(int argc, char **argv)
{
char **argw;
unsigned int buffer_size = 1024 * 1024;
int c, option_index = 0;
int c;
unsigned int n_tx = 0, n_rx = 0;
static struct iio_context *ctx;
static struct xflow_pthread_data xflow_pthread_data;
Expand All @@ -165,13 +167,18 @@ int main(int argc, char **argv)
struct iio_device *dev;
char unit;
int ret;
struct option *opts;

argw = dup_argv(MY_NAME, argc, argv);

ctx = handle_common_opts(MY_NAME, argc, argw, options, options_descriptions);

while ((c = getopt_long(argc, argw, "+" COMMON_OPTIONS "s:a", /* Flawfinder: ignore */
options, &option_index)) != -1) {
ctx = handle_common_opts(MY_NAME, argc, argw, MY_OPTS, options, options_descriptions);
opts = add_common_options(options);
if (!opts) {
fprintf(stderr, "Failed to add common options\n");
return EXIT_FAILURE;
}
while ((c = getopt_long(argc, argw, "+" COMMON_OPTIONS MY_OPTS, /* Flawfinder: ignore */
opts, NULL)) != -1) {
switch (c) {
/* All these are handled in the common */
case 'h':
Expand All @@ -181,7 +188,8 @@ int main(int argc, char **argv)
break;
case 'S':
case 'a':
if (!optarg && argv[optind] != NULL && argv[optind][0] != '-')
if (!optarg && argc > optind && argv[optind] != NULL
&& argv[optind][0] != '-')
optind++;
break;

Expand All @@ -204,6 +212,7 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
}
free(opts);

if (optind + 1 != argc) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
Expand Down
20 changes: 14 additions & 6 deletions tests/iio_attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -340,11 +340,12 @@ static const char *options_descriptions[] = {
"Read/Write debug attributes.",
};

#define MY_OPTS "CdcBDiosIqg:"
int main(int argc, char **argv)
{
char **argw;
struct iio_context *ctx;
int c, option_index = 0;
int c;
int device_index = 0, channel_index = 0, attr_index = 0;
const char *gen_file = NULL;
bool search_device = false, ignore_case = false,
Expand All @@ -356,13 +357,18 @@ int main(int argc, char **argv)
channel_found = false ;
unsigned int i;
char *wbuf = NULL;
struct option *opts;

argw = dup_argv(MY_NAME, argc, argv);

ctx = handle_common_opts(MY_NAME, argc, argw, options, options_descriptions);

while ((c = getopt_long(argc, argw, "+" COMMON_OPTIONS "g:CdcBDiosIq", /* Flawfinder: ignore */
options, &option_index)) != -1) {
ctx = handle_common_opts(MY_NAME, argc, argw, MY_OPTS, options, options_descriptions);
opts = add_common_options(options);
if (!opts) {
fprintf(stderr, "Failed to add common options\n");
return EXIT_FAILURE;
}
while ((c = getopt_long(argc, argw, "+" COMMON_OPTIONS MY_OPTS, /* Flawfinder: ignore */
opts, NULL)) != -1) {
switch (c) {
/* All these are handled in the common */
case 'h':
Expand All @@ -372,7 +378,8 @@ int main(int argc, char **argv)
break;
case 'S':
case 'a':
if (!optarg && argv[optind] != NULL && argv[optind][0] != '-')
if (!optarg && argc > optind && argv[optind] != NULL
&& argv[optind][0] != '-')
optind++;
break;
/* Attribute type
Expand Down Expand Up @@ -424,6 +431,7 @@ int main(int argc, char **argv)
}
}

free(opts);

if (!ctx)
return EXIT_FAILURE;
Expand Down
79 changes: 68 additions & 11 deletions tests/iio_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,43 @@ static const struct option common_options[] = {
{0, 0, 0, 0},
};

struct option * add_common_options(const struct option * longopts)
{
int i = 0, j = 0;
struct option *opts;

while (longopts[i].name) {
i++;
}
while (common_options[j].name) {
j++;
i++;
}
opts = calloc(i + 1, sizeof(struct option));
if (!opts) {
fprintf(stderr, "Out of memory\n");
return NULL;
}
i = 0, j = 0;
while (longopts[i].name) {
opts[i].name = longopts[i].name;
opts[i].has_arg = longopts[i].has_arg;
opts[i].flag = longopts[i].flag;
opts[i].val = longopts[i].val;
i++;
}
while (common_options[j].name) {
opts[i].name = common_options[j].name;
opts[i].has_arg = common_options[j].has_arg;
opts[i].flag = common_options[j].flag;
opts[i].val = common_options[j].val;
i++;
j++;
}

return opts;
}

static const char *common_options_descriptions[] = {
"Show this help and quit.",
"Use the XML backend with the provided XML file.",
Expand All @@ -207,22 +244,32 @@ static const char *common_options_descriptions[] = {
};


struct iio_context * handle_common_opts(char * name, int argc, char * const argv[],
struct iio_context * handle_common_opts(char * name, int argc,
char * const argv[], const char *optstring,
const struct option *options, const char *options_descriptions[])
{
struct iio_context *ctx = NULL;
int c, option_index = 0;
int c;
enum backend backend = IIO_LOCAL;
const char *arg = NULL;
bool do_scan = false, detect_context = false;
char buf[128];
struct option *opts;

/* Setting opterr to zero disables error messages from getopt_long */
opterr = 0;
/* start over at first index */
optind = 1;

while ((c = getopt_long(argc, argv, COMMON_OPTIONS, /* Flawfinder: ignore */
common_options, &option_index)) != -1) {
iio_snprintf(buf, sizeof(buf), "%s%s", COMMON_OPTIONS, optstring);
opts = add_common_options(options);
if (!opts) {
fprintf(stderr, "Failed to add common options\n");
return NULL;
}

while ((c = getopt_long(argc, argv, buf, /* Flawfinder: ignore */
opts, NULL)) != -1) {
switch (c) {
case 'h':
usage(name, options, options_descriptions);
Expand Down Expand Up @@ -272,7 +319,7 @@ struct iio_context * handle_common_opts(char * name, int argc, char * const argv
if (optarg) {
arg = optarg;
} else {
if (argv[optind] && argv[optind][0] != '-')
if (argc > optind && argv[optind] && argv[optind][0] != '-')
arg = argv[optind++];
}
break;
Expand All @@ -281,20 +328,21 @@ struct iio_context * handle_common_opts(char * name, int argc, char * const argv
if (optarg) {
arg = optarg;
} else {
if (argv[optind] && argv[optind][0] != '-')
if (argc > optind && argv[optind] && argv[optind][0] != '-')
arg = argv[optind++];
}
break;
case '?':
break;
}
}
free(opts);
optind = 1;
opterr = 1;

if (do_scan) {
autodetect_context(false, name, arg);
exit(0);
return NULL;
} else if (detect_context)
ctx = autodetect_context(true, name, arg);
else if (!arg && backend != IIO_LOCAL)
Expand Down Expand Up @@ -329,14 +377,23 @@ void usage(char *name, const struct option *options,
printf("\t%s [OPTION]...\t%s\n", name, options_descriptions[0]);
printf("Options:\n");
for (i = 0; common_options[i].name; i++) {
printf("\t-%c, --%s\n\t\t\t%s\n",
common_options[i].val, common_options[i].name,
printf("\t-%c, --%s", common_options[i].val, common_options[i].name);
if (common_options[i].has_arg == required_argument)
printf(" [arg]");
else if (common_options[i].has_arg == optional_argument)
printf(" <arg>");
printf("\n\t\t\t%s\n",
common_options_descriptions[i]);
}
for (i = 0; options[i].name; i++) {
printf("\t-%c, --%s\n\t\t\t%s\n",
options[i].val, options[i].name,
printf("\t-%c, --%s", options[i].val, options[i].name);
if (options[i].has_arg == required_argument)
printf(" [arg]");
else if (options[i].has_arg == optional_argument)
printf(" <arg>");
printf("\n\t\t\t%s\n",
options_descriptions[i + 1]);

}
printf("\nThis is free software; see the source for copying conditions. There is NO\n"
"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
Expand Down
9 changes: 8 additions & 1 deletion tests/iio_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,16 @@ struct iio_context * autodetect_context(bool rtn, const char *name, const char *
unsigned long int sanitize_clamp(const char *name, const char *argv,
uint64_t min, uint64_t max);

/* optstring is a string containing the legitimate option characters.
* If such a character is followed by a colon, the option requires an argument.
* Two colons mean an option takes an optional argument.
*/
#define COMMON_OPTIONS "hn:x:u:a::S::"
struct iio_context * handle_common_opts(char * name, int argc, char * const argv[],

struct iio_context * handle_common_opts(char * name, int argc,
char * const argv[], const char *optstring,
const struct option *options, const char *options_descriptions[]);
struct option * add_common_options(const struct option * longopts);
void usage(char *name, const struct option *options, const char *options_descriptions[]);

char ** dup_argv(char * name, int argc, char * argv[]);
Expand Down
17 changes: 12 additions & 5 deletions tests/iio_genxml.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,19 @@ int main(int argc, char **argv)
char *xml;
const char *tmp;
struct iio_context *ctx;
int c, option_index = 0;
int c;
size_t xml_len;
struct option *opts;

argw = dup_argv(MY_NAME, argc, argv);
ctx = handle_common_opts(MY_NAME, argc, argw, options, options_descriptions);

ctx = handle_common_opts(MY_NAME, argc, argw, "", options, options_descriptions);
opts = add_common_options(options);
if (!opts) {
fprintf(stderr, "Failed to add common options\n");
return EXIT_FAILURE;
}
while ((c = getopt_long(argc, argv, "+" COMMON_OPTIONS, /* Flawfinder: ignore */
options, &option_index)) != -1) {
opts, NULL)) != -1) {
switch (c) {
/* All these are handled in the common */
case 'h':
Expand All @@ -61,14 +66,16 @@ int main(int argc, char **argv)
break;
case 'S':
case 'a':
if (!optarg && argv[optind] != NULL && argv[optind][0] != '-')
if (!optarg && argc > optind && argv[optind] != NULL
&& argv[optind][0] != '-')
optind++;
break;
case '?':
printf("Unknown argument '%c'\n", c);
return EXIT_FAILURE;
}
}
free(opts);

if (optind != argc) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
Expand Down
20 changes: 15 additions & 5 deletions tests/iio_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,17 @@ static int dev_is_buffer_capable(const struct iio_device *dev)
return false;
}

#define MY_OPTS "s"

int main(int argc, char **argv)
{
char **argw;
struct iio_context *ctx;
int c, option_index = 0;
int c;
unsigned int i, major, minor;
char git_tag[8];
int ret;
struct option *opts;

argw = dup_argv(MY_NAME, argc, argv);

Expand All @@ -78,8 +81,14 @@ int main(int argc, char **argv)
printf(" %s", iio_get_backend(i));
printf("\n");

while ((c = getopt_long(argc, argw, "+" COMMON_OPTIONS "s", /* Flawfinder: ignore */
options, &option_index)) != -1) {
ctx = handle_common_opts(MY_NAME, argc, argw, MY_OPTS, options, options_descriptions);
opts = add_common_options(options);
if (!opts) {
fprintf(stderr, "Failed to add common options\n");
return EXIT_FAILURE;
}
while ((c = getopt_long(argc, argw, "+" COMMON_OPTIONS MY_OPTS, /* Flawfinder: ignore */
opts, NULL)) != -1) {
switch (c) {
/* All these are handled in the common */
case 'h':
Expand All @@ -89,7 +98,8 @@ int main(int argc, char **argv)
break;
case 'S':
case 'a':
if (!optarg && argv[optind] != NULL && argv[optind][0] != '-')
if (!optarg && argc > optind && argw[optind] != NULL
&& argw[optind][0] != '-')
optind++;
break;
case 's':
Expand All @@ -100,14 +110,14 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}
}
free(opts);

if (optind != argc) {
fprintf(stderr, "Incorrect number of arguments.\n\n");
usage(MY_NAME, options, options_descriptions);
return EXIT_FAILURE;
}

ctx = handle_common_opts(MY_NAME, argc, argw, options, options_descriptions);
if (!ctx)
return EXIT_FAILURE;

Expand Down
Loading