From 0f7d46af3153fde994865cbe1015bbc941aeb9a1 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Mon, 11 May 2020 11:40:15 -0400 Subject: [PATCH] tests: add a common function to parse and create iio_contexts Some (older) implementations of getopt_long) do not protect against internal buffer overflows, so copy argv to a temp str array, and parse most in a common function. (-u -h -x -n, and -S). -h, --help Show this help and quit. -x, --xml Use the XML backend with the provided XML file. -u, --uri Use the context at the provided URI. -S, --scan Scan for available backends. -a, --auto Scan for available contexts and if only one is available use it. The "default" for scan is "S", since "s" is used for many apps as sample size. This means that iio_info now takes -s and -S as scan. This also fixes both CWE-120 and CWE-20 https://cwe.mitre.org/data/definitions/120.html https://cwe.mitre.org/data/definitions/20.html and almost is a net decrease (348 insertions, 345 deletions over 9 files). Signed-off-by: Robin Getz --- tests/iio_adi_xflow_check.c | 57 +++++--------- tests/iio_attr.c | 107 ++++++++++---------------- tests/iio_common.c | 147 ++++++++++++++++++++++++++++++++++++ tests/iio_common.h | 7 ++ tests/iio_genxml.c | 56 +++----------- tests/iio_info.c | 105 ++++++-------------------- tests/iio_readdev.c | 55 +++++--------- tests/iio_reg.c | 104 ++++++++++++++----------- tests/iio_writedev.c | 55 +++++--------- 9 files changed, 348 insertions(+), 345 deletions(-) diff --git a/tests/iio_adi_xflow_check.c b/tests/iio_adi_xflow_check.c index b01205011..22ffa6727 100644 --- a/tests/iio_adi_xflow_check.c +++ b/tests/iio_adi_xflow_check.c @@ -39,9 +39,6 @@ struct xflow_pthread_data { }; static const struct option options[] = { - {"help", no_argument, 0, 'h'}, - {"network", required_argument, 0, 'n'}, - {"uri", required_argument, 0, 'u'}, {"buffer-size", required_argument, 0, 's'}, {"auto", no_argument, 0, 'a'}, {0, 0, 0, 0}, @@ -49,9 +46,6 @@ static const struct option options[] = { static const char *options_descriptions[] = { "[-n ] [-u ] [-a ] [-s ] ", - "Show this help and quit.", - "Use the network backend with the provided hostname.", - "Use the context with the provided URI.", "Size of the buffer in sample sets. Default is 1Msample", "Scan for available contexts and if only one is available use it.", }; @@ -158,14 +152,12 @@ static void *monitor_thread_fn(void *data) int main(int argc, char **argv) { + char **argw; unsigned int buffer_size = 1024 * 1024; int c, option_index = 0; - const char *arg_uri = NULL; - const char *arg_ip = NULL; unsigned int n_tx = 0, n_rx = 0; static struct iio_context *ctx; static struct xflow_pthread_data xflow_pthread_data; - bool scan_for_context = false; unsigned int i, nb_channels; struct iio_buffer *buffer; pthread_t monitor_thread; @@ -174,12 +166,22 @@ int main(int argc, char **argv) char unit; int ret; - while ((c = getopt_long(argc, argv, "+hn:u:s:a", + argw = dup_argv(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) { switch (c) { + /* All these are handled in the common */ case 'h': - usage(MY_NAME, options, options_descriptions); - return EXIT_SUCCESS; + case 'n': + case 'x': + case 'S': + case 'u': + case 'a': + break; + case 's': ret = sscanf(optarg, "%u%c", &buffer_size, &unit); if (ret == 0) @@ -191,15 +193,6 @@ int main(int argc, char **argv) buffer_size *= 1024 * 1024; } break; - case 'n': - arg_ip = optarg; - break; - case 'u': - arg_uri = optarg; - break; - case 'a': - scan_for_context = true; - break; case '?': return EXIT_FAILURE; } @@ -211,6 +204,9 @@ int main(int argc, char **argv) return EXIT_FAILURE; } + if (!ctx) + return EXIT_FAILURE; + #ifndef _WIN32 set_handler(SIGHUP, &quit_all); #endif @@ -218,22 +214,7 @@ int main(int argc, char **argv) set_handler(SIGSEGV, &quit_all); set_handler(SIGTERM, &quit_all); - - if (scan_for_context) - ctx = autodetect_context(true, NULL, MY_NAME); - else if (arg_uri) - ctx = iio_create_context_from_uri(arg_uri); - else if (arg_ip) - ctx = iio_create_network_context(arg_ip); - else - ctx = iio_create_default_context(); - - if (!ctx) { - fprintf(stderr, "Unable to create IIO context\n"); - return EXIT_FAILURE; - } - - device_name = argv[optind]; + device_name = argw[optind]; dev = get_device(ctx, device_name); if (!dev) { @@ -302,6 +283,6 @@ int main(int argc, char **argv) iio_buffer_destroy(buffer); iio_context_destroy(ctx); - + free_argw(argc, argw); return 0; } diff --git a/tests/iio_attr.c b/tests/iio_attr.c index 9df19ebf5..bfa1f79c9 100644 --- a/tests/iio_attr.c +++ b/tests/iio_attr.c @@ -297,14 +297,9 @@ static void dump_channel_attributes(const struct iio_device *dev, } static const struct option options[] = { - /* help */ - {"help", no_argument, 0, 'h'}, {"ignore-case", no_argument, 0, 'I'}, {"quiet", no_argument, 0, 'q'}, {"generate-code", required_argument, 0, 'g'}, - /* context connection */ - {"auto", no_argument, 0, 'a'}, - {"uri", required_argument, 0, 'u'}, /* Channel qualifiers */ {"input-channel", no_argument, 0, 'i'}, {"output-channel", no_argument, 0, 'o'}, @@ -325,13 +320,9 @@ static const char *options_descriptions[] = { "\t\t\t\t-D [device] [attr] [value]\n" "\t\t\t\t-C [attr]", /* help */ - "Show this help and quit.", "Ignore case distinctions.", "Return result only.", "Generate code.", - /* context connection */ - "Use the first context found.", - "Use the context at the provided URI.", /* Channel qualifiers */ "Filter Input Channels only.", "Filter Output Channels only.", @@ -346,32 +337,32 @@ static const char *options_descriptions[] = { int main(int argc, char **argv) { + char **argw; struct iio_context *ctx; int c, option_index = 0; int device_index = 0, channel_index = 0, attr_index = 0; - const char *arg_uri = NULL, *gen_file = NULL; - enum backend backend = IIO_LOCAL; - bool detect_context = false, search_device = false, ignore_case = false, + const char *gen_file = NULL; + bool search_device = false, ignore_case = false, search_channel = false, search_buffer = false, search_debug = false, search_context = false, input_only = false, output_only = false, scan_only = false, quiet = false, gen_code = false; unsigned int i; char *wbuf = NULL; - while ((c = getopt_long(argc, argv, "+hau:g:CdcBDiosIq", + argw = dup_argv(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) { switch (c) { - /* help */ + /* All these are handled in the common */ case 'h': - usage(MY_NAME, options, options_descriptions); - return EXIT_SUCCESS; - /* context connection */ - case 'a': - detect_context = true; - break; + case 'n': + case 'x': + case 'S': case 'u': - backend = IIO_AUTO; - arg_uri = optarg; + case 'a': break; /* Attribute type * 'd'evice, 'c'hannel, 'C'ontext, 'B'uffer or 'D'ebug @@ -418,6 +409,10 @@ int main(int argc, char **argv) } } + + if (!ctx) + return EXIT_FAILURE; + if (gen_code) { if (!gen_test_path(gen_file)) { fprintf(stderr, "Can't write to %s to generate file\n", gen_file); @@ -460,7 +455,7 @@ int main(int argc, char **argv) if (argc >= optind + 2) attr_index = optind + 1; if (argc >= optind + 3) - wbuf = argv[optind + 2]; + wbuf = argw[optind + 2]; if (argc >= optind + 4) { fprintf(stderr, "Too many options for searching for device attributes\n"); return EXIT_FAILURE; @@ -479,7 +474,7 @@ int main(int argc, char **argv) if (argc >= optind + 3) attr_index = optind + 2; if (argc >= optind + 4) - wbuf = argv[optind + 3]; + wbuf = argw[optind + 3]; if (argc >= optind + 5) { fprintf(stderr, "Too many options for searching for channel attributes\n"); return EXIT_FAILURE; @@ -496,7 +491,7 @@ int main(int argc, char **argv) if (argc >= optind + 2) attr_index = optind + 1; if (argc >= optind + 3) - wbuf = argv[optind + 2]; + wbuf = argw[optind + 2]; if (argc >= optind + 4) { fprintf(stderr, "Too many options for searching for buffer attributes\n"); return EXIT_FAILURE; @@ -514,7 +509,7 @@ int main(int argc, char **argv) if (argc >= optind + 2) attr_index = optind + 1; if (argc >= optind + 3) - wbuf = argv[optind + 2]; + wbuf = argw[optind + 2]; if (argc >= optind + 4) { fprintf(stderr, "Too many options for searching for device attributes\n"); return EXIT_FAILURE; @@ -529,18 +524,18 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - if (device_index && !argv[device_index]) + if (device_index && !argw[device_index]) return EXIT_FAILURE; - if (channel_index && !argv[channel_index]) + if (channel_index && !argw[channel_index]) return EXIT_FAILURE; - if (attr_index && !argv[attr_index]) + if (attr_index && !argw[attr_index]) return EXIT_FAILURE; - if ((gen_code || wbuf) && ((device_index && (!strcmp(".", argv[device_index]) || - strchr(argv[device_index], '*'))) || - (channel_index && (!strcmp(".", argv[channel_index]) || - strchr(argv[channel_index], '*'))) || - (attr_index && (!strcmp(".", argv[attr_index]) || - strchr(argv[attr_index], '*'))))) { + if ((gen_code || wbuf) && ((device_index && (!strcmp(".", argw[device_index]) || + strchr(argw[device_index], '*'))) || + (channel_index && (!strcmp(".", argw[channel_index]) || + strchr(argw[channel_index], '*'))) || + (attr_index && (!strcmp(".", argw[attr_index]) || + strchr(argw[attr_index], '*'))))) { printf("can't %s with wildcard match\n", gen_code ? "generate code" : "write value"); return EXIT_FAILURE; @@ -550,27 +545,6 @@ int main(int argc, char **argv) gen_start(gen_file); } - if (detect_context) - ctx = autodetect_context(true, gen_code, MY_NAME); - else if (backend == IIO_AUTO) { - ctx = iio_create_context_from_uri(arg_uri); - gen_context(arg_uri); - } else - ctx = iio_create_default_context(); - - if (!ctx) { - if (!detect_context) { - char *buf = xmalloc(BUF_SIZE, MY_NAME); - - iio_strerror(errno, buf, BUF_SIZE); - fprintf(stderr, "Unable to create IIO context: %s\n", - buf); - free(buf); - } - gen_context_destroy(); - return EXIT_FAILURE; - } - if (search_context) { unsigned int nb_ctx_attrs = iio_context_get_attrs_count(ctx); if (!attr_index && nb_ctx_attrs > 0) @@ -582,7 +556,7 @@ int main(int argc, char **argv) ret = iio_context_get_attr(ctx, i, &key, &value); if (!ret) { - if (!attr_index || str_match(key, argv[attr_index], ignore_case)) { + if (!attr_index || str_match(key, argw[attr_index], ignore_case)) { printf("%s: %s\n", key, value); gen_context_attr(key); } @@ -609,8 +583,8 @@ int main(int argc, char **argv) const char *dev_id = iio_device_get_id(dev); unsigned int nb_attrs, nb_channels, j; - if (device_index && !str_match(dev_id, argv[device_index], ignore_case) - && !str_match(name, argv[device_index], ignore_case)) { + if (device_index && !str_match(dev_id, argw[device_index], ignore_case) + && !str_match(name, argw[device_index], ignore_case)) { continue; } @@ -651,8 +625,8 @@ int main(int argc, char **argv) ch_name = iio_channel_get_name(ch); if (channel_index && !str_match(iio_channel_get_id(ch), - argv[channel_index], ignore_case) && - (!ch_name || !str_match(ch_name,argv[channel_index], ignore_case))) + argw[channel_index], ignore_case) && + (!ch_name || !str_match(ch_name,argw[channel_index], ignore_case))) continue; if ((!scan_only && !channel_index) || @@ -712,7 +686,7 @@ int main(int argc, char **argv) iio_channel_get_attr(ch, k); if (attr_index && - !str_match(attr, argv[attr_index], + !str_match(attr, argw[attr_index], ignore_case)) continue; gen_dev(dev); @@ -732,7 +706,7 @@ int main(int argc, char **argv) const char *attr = iio_device_get_attr(dev, j); if (attr_index && - !str_match(attr, argv[attr_index], ignore_case)) + !str_match(attr, argw[attr_index], ignore_case)) continue; gen_dev(dev); @@ -752,7 +726,7 @@ int main(int argc, char **argv) for (j = 0; j < nb_attrs; j++) { const char *attr = iio_device_get_buffer_attr(dev, j); - if ((attr_index && str_match(attr, argv[attr_index], + if ((attr_index && str_match(attr, argw[attr_index], ignore_case)) || !attr_index) { gen_dev(dev); dump_buffer_attributes(dev, attr, wbuf, @@ -773,7 +747,7 @@ int main(int argc, char **argv) for (j = 0; j < nb_attrs; j++) { const char *attr = iio_device_get_debug_attr(dev, j); - if ((attr_index && str_match(attr, argv[attr_index], + if ((attr_index && str_match(attr, argw[attr_index], ignore_case)) || !attr_index) { gen_dev(dev); dump_debug_attributes(dev, attr, wbuf, @@ -788,8 +762,9 @@ int main(int argc, char **argv) iio_context_destroy(ctx); - if (gen_code) + if (gen_code) gen_context_destroy(); + free_argw(argc, argw); return EXIT_SUCCESS; } diff --git a/tests/iio_common.c b/tests/iio_common.c index 220d40310..3b664f4cb 100644 --- a/tests/iio_common.c +++ b/tests/iio_common.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -149,6 +150,143 @@ unsigned long int sanitize_clamp(const char *name, const char *argv, return (unsigned long int) val; } +char ** dup_argv(int argc, char * argv[]) +{ + int i = 1; + char** new_argv = xmalloc((argc + 1) * sizeof(char *), NULL); + + for(int i = 0; i < argc; i++) { + new_argv[i] = cmn_strndup(argv[i], NAME_MAX); + if (!new_argv[i]) + goto err_dup; + } + + return new_argv; + +err_dup: + i--; + for (; i >= 0; i--) + free(new_argv[i]); + + fprintf(stderr, "out of memory\n"); + exit(0); +} + +void free_argw(int argc, char * argv[]) +{ + int i; + + for(i = 0; i < argc; i++) { + free(argv[i]); + } + free(argv); +} + +static const struct option common_options[] = { + {"help", no_argument, 0, 'h'}, + {"xml", required_argument, 0, 'x'}, + {"uri", required_argument, 0, 'u'}, + {"scan", no_argument, 0, 'S'}, + {"auto", no_argument, 0, 'a'}, + {0, 0, 0, 0}, +}; + +static const char *common_options_descriptions[] = { + "Show this help and quit.", + "Use the XML backend with the provided XML file.", + "Use the context at the provided URI.", + "Scan for available backends.", + "Scan for available contexts and if only one is available use it.", +}; + + +struct iio_context * handle_common_opts(char * name, int argc, char * const argv[], + const struct option *options, const char *options_descriptions[]) +{ + struct iio_context *ctx = NULL; + int c, option_index = 0; + enum backend backend = IIO_LOCAL; + const char *arg = NULL; + bool do_scan = false, detect_context = false; + + /* 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) { + switch (c) { + case 'h': + usage(name, options, options_descriptions); + return NULL; + case 'n': + if (backend != IIO_LOCAL) { + fprintf(stderr, "-a, -x, -n and -u are mutually exclusive\n"); + return NULL; + } + backend = IIO_NETWORK; + arg = optarg; + break; + case 'x': + if (backend != IIO_LOCAL) { + fprintf(stderr, "-a, -x, -n and -u are mutually exclusive\n"); + return NULL; + } + backend = IIO_XML; + arg = optarg; + break; + case 'u': + if (backend != IIO_LOCAL) { + fprintf(stderr, "-a, -x, -n and -u are mutually exclusive\n"); + return NULL; + } + backend = IIO_AUTO; + arg = optarg; + break; + case 'a': + if (backend != IIO_LOCAL) { + fprintf(stderr, "-a, -x, -n and -u are mutually exclusive\n"); + return NULL; + } + detect_context = true; + break; + case 'S': + do_scan = true; + break; + case '?': + break; + } + } + optind = 1; + opterr = 1; + + if (do_scan) { + autodetect_context(false, false, name); + exit(0); + } else if (detect_context) + ctx = autodetect_context(true, false, name); + else if (!arg && backend != IIO_LOCAL) + fprintf(stderr, "argument parsing error\n"); + else if (backend == IIO_XML) + ctx = iio_create_xml_context(arg); + else if (backend == IIO_NETWORK) + ctx = iio_create_network_context(arg); + else if (backend == IIO_AUTO) + ctx = iio_create_context_from_uri(arg); + else + ctx = iio_create_default_context(); + + if (!ctx && !do_scan && !detect_context) { + char buf[1024]; + iio_strerror(errno, buf, sizeof(buf)); + if (arg) + fprintf(stderr, "Unable to create IIO context %s: %s\n", arg, buf); + else + fprintf(stderr, "Unable to create Local IIO context : %s\n", buf); + } + + return ctx; +} void usage(char *name, const struct option *options, const char *options_descriptions[]) @@ -158,10 +296,19 @@ void usage(char *name, const struct option *options, printf("Usage:\n"); 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, + 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, 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"); + + exit(0); } diff --git a/tests/iio_common.h b/tests/iio_common.h index 006c901af..3f096a8a7 100644 --- a/tests/iio_common.h +++ b/tests/iio_common.h @@ -45,8 +45,15 @@ char *cmn_strndup(const char *str, size_t n); struct iio_context * autodetect_context(bool rtn, bool gen_code, const char *name); unsigned long int sanitize_clamp(const char *name, const char *argv, uint64_t min, uint64_t max); + +#define COMMON_OPTIONS "hn:x:u:aS" +struct iio_context * handle_common_opts(char * name, int argc, char * const argv[], + const struct option *options, const char *options_descriptions[]); void usage(char *name, const struct option *options, const char *options_descriptions[]); +char ** dup_argv(int argc, char * argv[]); +void free_argw(int argc, char * argw[]); + /* https://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html * {NAME_MAX} : Maximum number of bytes in a filename * {PATH_MAX} : Maximum number of bytes in a pathname diff --git a/tests/iio_genxml.c b/tests/iio_genxml.c index 21691281d..19ea4d743 100644 --- a/tests/iio_genxml.c +++ b/tests/iio_genxml.c @@ -29,62 +29,40 @@ #define MY_NAME "iio_genxml" static const struct option options[] = { - {"help", no_argument, 0, 'h'}, - {"xml", required_argument, 0, 'x'}, - {"network", required_argument, 0, 'n'}, - {"uri", required_argument, 0, 'u'}, - {0, 0, 0, 0}, + {0, 0, 0, 0}, }; static const char *options_descriptions[] = { "\t[-x ]\n" "\t\t\t\t[-u ]\n" "\t\t\t\t[-n ]", - "Show this help and quit.", - "Use the XML backend with the provided XML file.", - "Use the network backend with the provided hostname.", - "Use the context with the provided URI.", }; int main(int argc, char **argv) { + char **argw; char *xml; const char *tmp; struct iio_context *ctx; int c, option_index = 0; - const char *arg_uri = NULL; - const char *arg_xml = NULL; - const char *arg_ip = NULL; size_t xml_len; - enum backend backend = IIO_LOCAL; - while ((c = getopt_long(argc, argv, "+hn:x:u:", + argw = dup_argv(argc, argv); + ctx = handle_common_opts(MY_NAME, argc, argw, options, options_descriptions); + + while ((c = getopt_long(argc, argv, "+" COMMON_OPTIONS, /* Flawfinder: ignore */ options, &option_index)) != -1) { switch (c) { + /* All these are handled in the common */ case 'h': - usage(MY_NAME, options, options_descriptions); - return EXIT_SUCCESS; case 'n': - if (backend != IIO_LOCAL) { - fprintf(stderr, "-x and -n are mutually exclusive\n"); - return EXIT_FAILURE; - } - backend = IIO_NETWORK; - arg_ip = optarg; - break; case 'x': - if (backend != IIO_LOCAL) { - fprintf(stderr, "-x and -n are mutually exclusive\n"); - return EXIT_FAILURE; - } - backend = IIO_XML; - arg_xml = optarg; - break; + case 'S': case 'u': - arg_uri = optarg; - backend = IIO_AUTO; + case 'a': break; case '?': + printf("Unknown argument '%c'\n", c); return EXIT_FAILURE; } } @@ -95,19 +73,8 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - if (backend == IIO_AUTO) - ctx = iio_create_context_from_uri(arg_uri); - else if (backend == IIO_XML) - ctx = iio_create_xml_context(arg_xml); - else if (backend == IIO_NETWORK) - ctx = iio_create_network_context(arg_ip); - else - ctx = iio_create_default_context(); - - if (!ctx) { - fprintf(stderr, "Unable to create IIO context\n"); + if (!ctx) return EXIT_FAILURE; - } tmp = iio_context_get_xml(ctx); if (!tmp) { @@ -132,6 +99,7 @@ int main(int argc, char **argv) printf("Context re-creation from generated XML succeeded!\n"); iio_context_destroy(ctx); } + free_argw(argc, argw); free(xml); return EXIT_SUCCESS; } diff --git a/tests/iio_info.c b/tests/iio_info.c index 003e5651f..541bf6f3a 100644 --- a/tests/iio_info.c +++ b/tests/iio_info.c @@ -35,25 +35,14 @@ #endif static const struct option options[] = { - {"help", no_argument, 0, 'h'}, - {"xml", required_argument, 0, 'x'}, - {"network", required_argument, 0, 'n'}, - {"uri", required_argument, 0, 'u'}, - {"scan", no_argument, 0, 's'}, - {"auto", no_argument, 0, 'a'}, - {0, 0, 0, 0}, + {"scan", no_argument, 0, 's'}, + {0, 0, 0, 0}, }; static const char *options_descriptions[] = { - "\t[-x ]\n" - "\t\t\t\t[-n ]\n" + "[-x ]\n" "\t\t\t\t[-u ]", - "Show this help and quit.", - "Use the XML backend with the provided XML file.", - "Use the network backend with the provided hostname.", - "Use the context at the provided URI.", "Scan for available backends.", - "Scan for available contexts and if only one is available use it.", }; static int dev_is_buffer_capable(const struct iio_device *dev) @@ -72,54 +61,39 @@ static int dev_is_buffer_capable(const struct iio_device *dev) int main(int argc, char **argv) { + char **argw; struct iio_context *ctx; int c, option_index = 0; - const char *arg_uri = NULL; - const char *arg_ip = NULL; - const char *arg_xml = NULL; - enum backend backend = IIO_LOCAL; - bool do_scan = false, detect_context = false; unsigned int i, major, minor; char git_tag[8]; int ret; - while ((c = getopt_long(argc, argv, "+hn:x:u:sa", + argw = dup_argv(argc, argv); + + iio_library_get_version(&major, &minor, git_tag); + printf("Library version: %u.%u (git tag: %s)\n", major, minor, git_tag); + + printf("Compiled with backends:"); + for (i = 0; i < iio_get_backends_count(); i++) + printf(" %s", iio_get_backend(i)); + printf("\n"); + + while ((c = getopt_long(argc, argw, "+" COMMON_OPTIONS "s", /* Flawfinder: ignore */ options, &option_index)) != -1) { switch (c) { + /* All these are handled in the common */ case 'h': - usage(MY_NAME, options, options_descriptions); - return EXIT_SUCCESS; case 'n': - if (backend != IIO_LOCAL) { - fprintf(stderr, "-x, -n and -u are mutually exclusive\n"); - return EXIT_FAILURE; - } - backend = IIO_NETWORK; - arg_ip = optarg; - break; case 'x': - if (backend != IIO_LOCAL) { - fprintf(stderr, "-x, -n and -u are mutually exclusive\n"); - return EXIT_FAILURE; - } - backend = IIO_XML; - arg_xml = optarg; - break; - case 's': - do_scan = true; - break; + case 'S': case 'u': - if (backend != IIO_LOCAL) { - fprintf(stderr, "-x, -n and -u are mutually exclusive\n"); - return EXIT_FAILURE; - } - backend = IIO_AUTO; - arg_uri = optarg; - break; case 'a': - detect_context = true; break; + case 's': + autodetect_context(false, false, MY_NAME); + return EXIT_SUCCESS; case '?': + printf("Unknown argument '%c'\n", c); return EXIT_FAILURE; } } @@ -130,41 +104,9 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - iio_library_get_version(&major, &minor, git_tag); - printf("Library version: %u.%u (git tag: %s)\n", major, minor, git_tag); - - printf("Compiled with backends:"); - for (i = 0; i < iio_get_backends_count(); i++) - printf(" %s", iio_get_backend(i)); - printf("\n"); - - if (do_scan) { - autodetect_context(false, false, MY_NAME); - return EXIT_SUCCESS; - } - - if (detect_context) - ctx = autodetect_context(true, false, MY_NAME); - else if (backend == IIO_XML) - ctx = iio_create_xml_context(arg_xml); - else if (backend == IIO_NETWORK) - ctx = iio_create_network_context(arg_ip); - else if (backend == IIO_AUTO) - ctx = iio_create_context_from_uri(arg_uri); - else - ctx = iio_create_default_context(); - - if (!ctx) { - if (!detect_context) { - char buf[1024]; - - iio_strerror(errno, buf, sizeof(buf)); - fprintf(stderr, "Unable to create IIO context: %s\n", - buf); - } - + ctx = handle_common_opts(MY_NAME, argc, argw, options, options_descriptions); + if (!ctx) return EXIT_FAILURE; - } printf("IIO context created with %s backend.\n", iio_context_get_name(ctx)); @@ -363,6 +305,7 @@ int main(int argc, char **argv) } } + free_argw(argc, argw); free(buf); iio_context_destroy(ctx); return EXIT_SUCCESS; diff --git a/tests/iio_readdev.c b/tests/iio_readdev.c index fad9bfd1d..8ff69a6ef 100644 --- a/tests/iio_readdev.c +++ b/tests/iio_readdev.c @@ -35,9 +35,6 @@ #define DEFAULT_FREQ_HZ 100 static const struct option options[] = { - {"help", no_argument, 0, 'h'}, - {"network", required_argument, 0, 'n'}, - {"uri", required_argument, 0, 'u'}, {"trigger", required_argument, 0, 't'}, {"buffer-size", required_argument, 0, 'b'}, {"samples", required_argument, 0, 's' }, @@ -47,11 +44,8 @@ static const struct option options[] = { }; static const char *options_descriptions[] = { - "[-n ] [-t ] [-T ] [-b ]" + "[-t ] [-T ] [-b ]" "[-s ] [ ...]", - "Show this help and quit.", - "Use the network backend with the provided hostname.", - "Use the context with the provided URI.", "Use the specified trigger.", "Size of the capture buffer. Default is 256.", "Number of samples to capture, 0 = infinite. Default is 0.", @@ -196,32 +190,30 @@ static ssize_t print_sample(const struct iio_channel *chn, int main(int argc, char **argv) { + char **argw; unsigned int i, nb_channels; unsigned int nb_active_channels = 0; unsigned int buffer_size = SAMPLES_PER_READ; - const char *arg_uri = NULL; - const char *arg_ip = NULL; int c, option_index = 0; struct iio_device *dev; ssize_t sample_size; int timeout = -1; - bool scan_for_context = false; ssize_t ret; - while ((c = getopt_long(argc, argv, "+hn:u:t:b:s:T:a", + argw = dup_argv(argc, argv); + + ctx = handle_common_opts(MY_NAME, argc, argw, options, options_descriptions); + + while ((c = getopt_long(argc, argw, "+" COMMON_OPTIONS "t:b:s:T:", /* Flawfinder: ignore */ options, &option_index)) != -1) { switch (c) { + /* All these are handled in the common */ case 'h': - usage(MY_NAME, options, options_descriptions); - return EXIT_SUCCESS; case 'n': - arg_ip = optarg; - break; + case 'x': + case 'S': case 'u': - arg_uri = optarg; - break; case 'a': - scan_for_context = true; break; case 't': trigger_name = optarg; @@ -236,6 +228,7 @@ int main(int argc, char **argv) timeout = sanitize_clamp("timeout", optarg, 0, INT_MAX); break; case '?': + printf("Unknown argument '%c'\n", c); return EXIT_FAILURE; } } @@ -246,21 +239,10 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - setup_sig_handler(); - - if (scan_for_context) - ctx = autodetect_context(true, false, MY_NAME); - else if (arg_uri) - ctx = iio_create_context_from_uri(arg_uri); - else if (arg_ip) - ctx = iio_create_network_context(arg_ip); - else - ctx = iio_create_default_context(); - - if (!ctx) { - fprintf(stderr, "Unable to create IIO context\n"); + if (!ctx) return EXIT_FAILURE; - } + + setup_sig_handler(); if (timeout >= 0) { ret = iio_context_set_timeout(ctx, timeout); @@ -272,9 +254,9 @@ int main(int argc, char **argv) } } - dev = iio_context_find_device(ctx, argv[optind]); + dev = iio_context_find_device(ctx, argw[optind]); if (!dev) { - fprintf(stderr, "Device %s not found\n", argv[optind]); + fprintf(stderr, "Device %s not found\n", argw[optind]); iio_context_destroy(ctx); return EXIT_FAILURE; } @@ -336,8 +318,8 @@ int main(int argc, char **argv) struct iio_channel *ch = iio_device_get_channel(dev, i); for (j = optind + 1; j < (unsigned int) argc; j++) { const char *n = iio_channel_get_name(ch); - if ((!strcmp(argv[j], iio_channel_get_id(ch)) || - (n && !strcmp(n, argv[j]))) && + if ((!strcmp(argw[j], iio_channel_get_id(ch)) || + (n && !strcmp(n, argw[j]))) && !iio_channel_is_output(ch)) { iio_channel_enable(ch); nb_active_channels++; @@ -431,5 +413,6 @@ int main(int argc, char **argv) err_destroy_buffer: iio_buffer_destroy(buffer); iio_context_destroy(ctx); + free_argw(argc, argw); return exit_code; } diff --git a/tests/iio_reg.c b/tests/iio_reg.c index 538705913..1525125e2 100644 --- a/tests/iio_reg.c +++ b/tests/iio_reg.c @@ -23,27 +23,23 @@ #include #include #include +#include #include "iio_common.h" -static int write_reg(const char *name, uint32_t addr, uint32_t val) -{ - struct iio_device *dev; - struct iio_context *ctx; - int ret; +#define MY_NAME "iio_reg" - ctx = iio_create_default_context(); - if (!ctx) { - perror("Unable to create context"); - return EXIT_FAILURE; - } +static const struct option options[] = { + {0, 0, 0, 0}, +}; - dev = iio_context_find_device(ctx, name); - if (!dev) { - errno = ENODEV; - perror("Unable to find device"); - goto err_destroy_context; - } +static const char *options_descriptions[] = { + " []\n" +}; + +static int write_reg(struct iio_device *dev, uint32_t addr, uint32_t val) +{ + int ret; ret = iio_device_reg_write(dev, addr, val); if (ret < 0) { @@ -52,34 +48,17 @@ static int write_reg(const char *name, uint32_t addr, uint32_t val) goto err_destroy_context; } - iio_context_destroy(ctx); return EXIT_SUCCESS; err_destroy_context: - iio_context_destroy(ctx); return EXIT_FAILURE; } -static int read_reg(const char *name, unsigned long addr) +static int read_reg(struct iio_device *dev, unsigned long addr) { - struct iio_device *dev; - struct iio_context *ctx; uint32_t val; int ret; - ctx = iio_create_default_context(); - if (!ctx) { - perror("Unable to create context"); - return EXIT_FAILURE; - } - - dev = iio_context_find_device(ctx, name); - if (!dev) { - errno = ENODEV; - perror("Unable to find device"); - goto err_destroy_context; - } - ret = iio_device_reg_read(dev, addr, &val); if (ret < 0) { errno = -ret; @@ -88,29 +67,66 @@ static int read_reg(const char *name, unsigned long addr) } printf("0x%x\n", val); - iio_context_destroy(ctx); return EXIT_SUCCESS; err_destroy_context: - iio_context_destroy(ctx); return EXIT_FAILURE; } int main(int argc, char **argv) { + char **argw; unsigned long addr; + struct iio_context *ctx; + struct iio_device *dev; + int c, option_index = 0; + char * name; + + argw = dup_argv(argc, argv); + + ctx = handle_common_opts(MY_NAME, argc, argw, options, options_descriptions); + + while ((c = getopt_long(argc, argw, "+" COMMON_OPTIONS, /* Flawfinder: ignore */ + options, &option_index)) != -1) { + switch (c) { + /* All these are handled in the common */ + case 'h': + case 'n': + case 'x': + case 'S': + case 'u': + case 'a': + break; + case '?': + printf("Unknown argument '%c'\n", c); + return EXIT_FAILURE; + } + } - if (argc < 3 || argc > 4) { - printf("Usage:\n\niio_reg []\n"); - return 0; + if ((argc - optind) < 2 || (argc - optind) > 3) { + usage(MY_NAME, options, options_descriptions); + return EXIT_SUCCESS; } - addr = sanitize_clamp("register address", argv[2], 0, UINT32_MAX); + name = cmn_strndup(argw[optind], NAME_MAX); + dev = iio_context_find_device(ctx, name); + if (!dev) { + perror("Unable to find device"); + goto err_destroy_context; + } - if (argc == 3) { - return read_reg(argv[1], addr); + addr = sanitize_clamp("register address", argw[optind + 1], 0, UINT32_MAX); + + if ((argc - optind) == 2) { + return read_reg(dev, addr); } else { - uint32_t val = sanitize_clamp("register value", argv[3], 0, UINT32_MAX); - return write_reg(argv[1], addr, val); + uint32_t val = sanitize_clamp("register value", argw[optind + 2], 0, UINT32_MAX); + return write_reg(dev, addr, val); } + +err_destroy_context: + free(name); + iio_context_destroy(ctx); + free_argw(argc, argw); + return EXIT_SUCCESS; } diff --git a/tests/iio_writedev.c b/tests/iio_writedev.c index 3eb6ce162..6ff15b298 100644 --- a/tests/iio_writedev.c +++ b/tests/iio_writedev.c @@ -44,9 +44,6 @@ #define DEFAULT_FREQ_HZ 100 static const struct option options[] = { - {"help", no_argument, 0, 'h'}, - {"network", required_argument, 0, 'n'}, - {"uri", required_argument, 0, 'u'}, {"trigger", required_argument, 0, 't'}, {"buffer-size", required_argument, 0, 'b'}, {"samples", required_argument, 0, 's' }, @@ -57,12 +54,9 @@ static const struct option options[] = { }; static const char *options_descriptions[] = { - "[-n ] [-t ] " + "[-t ] " "[-T ] [-b ] [-s ] " " [ ...]", - "Show this help and quit.", - "Use the network backend with the provided hostname.", - "Use the context with the provided URI.", "Use the specified trigger.", "Size of the transmit buffer. Default is 256.", "Number of samples to write, 0 = infinite. Default is 0.", @@ -206,33 +200,31 @@ static ssize_t read_sample(const struct iio_channel *chn, int main(int argc, char **argv) { + char **argw; unsigned int i, nb_channels; unsigned int nb_active_channels = 0; unsigned int buffer_size = SAMPLES_PER_READ; - const char *arg_uri = NULL; - const char *arg_ip = NULL; int c, option_index = 0; struct iio_device *dev; ssize_t sample_size; int timeout = -1; - bool scan_for_context = false; bool cyclic_buffer = false; ssize_t ret; - while ((c = getopt_long(argc, argv, "+hn:u:t:b:s:T:ac", + argw = dup_argv(argc, argv); + + ctx = handle_common_opts(MY_NAME, argc, argw, options, options_descriptions); + + while ((c = getopt_long(argc, argw, "+" COMMON_OPTIONS "t:b:s:T:ac", /* Flawfinder: ignore */ options, &option_index)) != -1) { switch (c) { + /* All these are handled in the common */ case 'h': - usage(MY_NAME, options, options_descriptions); - return EXIT_SUCCESS; case 'n': - arg_ip = optarg; - break; + case 'x': + case 'S': case 'u': - arg_uri = optarg; - break; case 'a': - scan_for_context = true; break; case 't': trigger_name = optarg; @@ -250,6 +242,7 @@ int main(int argc, char **argv) cyclic_buffer = true; break; case '?': + printf("Unknown argument '%c'\n", c); return EXIT_FAILURE; } } @@ -260,21 +253,10 @@ int main(int argc, char **argv) return EXIT_FAILURE; } - setup_sig_handler(); - - if (scan_for_context) - ctx = autodetect_context(true, false, MY_NAME); - else if (arg_uri) - ctx = iio_create_context_from_uri(arg_uri); - else if (arg_ip) - ctx = iio_create_network_context(arg_ip); - else - ctx = iio_create_default_context(); - - if (!ctx) { - fprintf(stderr, "Unable to create IIO context\n"); + if (!ctx) return EXIT_FAILURE; - } + + setup_sig_handler(); if (timeout >= 0) { ret = iio_context_set_timeout(ctx, timeout); @@ -286,9 +268,9 @@ int main(int argc, char **argv) } } - dev = iio_context_find_device(ctx, argv[optind]); + dev = iio_context_find_device(ctx, argw[optind]); if (!dev) { - fprintf(stderr, "Device %s not found\n", argv[optind]); + fprintf(stderr, "Device %s not found\n", argw[optind]); iio_context_destroy(ctx); return EXIT_FAILURE; } @@ -350,8 +332,8 @@ int main(int argc, char **argv) struct iio_channel *ch = iio_device_get_channel(dev, i); for (j = optind + 1; j < (unsigned int) argc; j++) { const char *n = iio_channel_get_name(ch); - if ((!strcmp(argv[j], iio_channel_get_id(ch)) || - (n && !strcmp(n, argv[j]))) && + if ((!strcmp(argw[j], iio_channel_get_id(ch)) || + (n && !strcmp(n, argw[j]))) && iio_channel_is_output(ch)) { iio_channel_enable(ch); nb_active_channels++; @@ -449,5 +431,6 @@ int main(int argc, char **argv) err_destroy_buffer: iio_buffer_destroy(buffer); iio_context_destroy(ctx); + free_argw(argc, argw); return exit_code; }