From 7f4df04d59b1182fb8497f16dc5588bd6e1d4225 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Fri, 26 Mar 2021 10:06:47 +1000 Subject: [PATCH] tools/record: deduplicate the device opening logic With a new helper function strv_from_argv we can re-use the device opening loop for all the use-cases we have. Signed-off-by: Peter Hutterer --- src/util-strings.c | 30 ++++++++++++++++++++++++++++++ src/util-strings.h | 1 + test/test-utils.c | 39 +++++++++++++++++++++++++++++++++++++++ tools/libinput-record.c | 44 ++++++++++++++++---------------------------- 4 files changed, 86 insertions(+), 28 deletions(-) diff --git a/src/util-strings.c b/src/util-strings.c index 7d4c462..4331a4b 100644 --- a/src/util-strings.c +++ b/src/util-strings.c @@ -59,6 +59,36 @@ next_word(const char **state, size_t *len, const char *separators) } /** + * Return a null-terminated string array with the contents of argv + * duplicated. + * + * Use strv_free() to free the array. + * + * @return A null-terminated string array or NULL on errors + */ +char** +strv_from_argv(int argc, char **argv) +{ + char **strv = NULL; + + assert(argc >= 0); + + if (argc == 0) + return NULL; + + strv = zalloc((argc + 1) * sizeof *strv); + for (int i = 0; i < argc; i++) { + char *copy = safe_strdup(argv[i]); + if (!copy) { + strv_free(strv); + return NULL; + } + strv[i] = copy; + } + return strv; +} + +/** * Return a null-terminated string array with the tokens in the input * string, e.g. "one two\tthree" with a separator list of " \t" will return * an array [ "one", "two", "three", NULL ]. diff --git a/src/util-strings.h b/src/util-strings.h index 9d04406..2a15fab 100644 --- a/src/util-strings.h +++ b/src/util-strings.h @@ -252,6 +252,7 @@ safe_atod(const char *str, double *val) return true; } +char **strv_from_argv(int argc, char **argv); char **strv_from_string(const char *in, const char *separator); char *strv_join(char **strv, const char *joiner); diff --git a/test/test-utils.c b/test/test-utils.c index dbd5803..882ee6c 100644 --- a/test/test-utils.c +++ b/test/test-utils.c @@ -1022,6 +1022,44 @@ START_TEST(strsplit_test) } END_TEST +START_TEST(strargv_test) +{ + struct argv_test { + int argc; + char *argv[10]; + int expected; + } tests[] = { + { 0, {NULL}, 0 }, + { 1, {"hello", "World"}, 1 }, + { 2, {"hello", "World"}, 2 }, + { 2, {"", " "}, 2 }, + { 2, {"", NULL}, 0 }, + { 2, {NULL, NULL}, 0 }, + { 1, {NULL, NULL}, 0 }, + { 3, {"hello", NULL, "World"}, 0 }, + }; + struct argv_test *t; + + ARRAY_FOR_EACH(tests, t) { + char **strv = strv_from_argv(t->argc, t->argv); + + if (t->expected == 0) { + ck_assert(strv == NULL); + } else { + int count = 0; + char **s = strv; + while (*s) { + ck_assert_str_eq(*s, t->argv[count]); + count++; + s++; + } + ck_assert_int_eq(t->expected, count); + strv_free(strv); + } + } +} +END_TEST + START_TEST(kvsplit_double_test) { struct kvsplit_dbl_test { @@ -1378,6 +1416,7 @@ litest_utils_suite(void) tcase_add_test(tc, safe_atou_base_8_test); tcase_add_test(tc, safe_atod_test); tcase_add_test(tc, strsplit_test); + tcase_add_test(tc, strargv_test); tcase_add_test(tc, kvsplit_double_test); tcase_add_test(tc, strjoin_test); tcase_add_test(tc, strstrip_test); diff --git a/tools/libinput-record.c b/tools/libinput-record.c index 0704db3..062a45a 100644 --- a/tools/libinput-record.c +++ b/tools/libinput-record.c @@ -2448,13 +2448,13 @@ mainloop(struct record_context *ctx) } static bool -init_device(struct record_context *ctx, char *path, bool grab) +init_device(struct record_context *ctx, const char *path, bool grab) { struct record_device *d; int fd, rc; d = zalloc(sizeof(*d)); - d->devnode = path; + d->devnode = safe_strdup(path); d->nevents = 0; d->events_sz = 5000; d->events = zalloc(d->events_sz * sizeof(*d->events)); @@ -2698,6 +2698,7 @@ main(int argc, char **argv) bool all = false, with_libinput = false, grab = false; int ndevices; int rc = EXIT_FAILURE; + char **paths = NULL; list_init(&ctx.devices); list_init(&ctx.sources); @@ -2791,39 +2792,25 @@ main(int argc, char **argv) goto out; } + /* Now collect all device paths and init our device struct */ if (all) { - char **devices; /* NULL-terminated */ - char **d; - - devices = all_devices(); - d = devices; - - while (*d) { - if (!init_device(&ctx, safe_strdup(*d), grab)) { - strv_free(devices); - goto out; - } - d++; - } - - strv_free(devices); - } else if (ndevices > 1) { - for (int i = ndevices; i > 0; i -= 1) { - char *devnode = safe_strdup(argv[optind + i - 1]); - - if (!init_device(&ctx, devnode, grab)) - goto out; - } + paths = all_devices(); + } else if (ndevices >= 1) { + paths = strv_from_argv(ndevices, &argv[optind]); } else { - char *path; - - path = ndevices <= 0 ? select_device() : safe_strdup(argv[optind++]); + char *path = select_device(); if (path == NULL) { goto out; } - if (!init_device(&ctx, path, grab)) + paths = strv_from_argv(1, &path); + free(path); + } + + for (char **p = paths; *p; p++) { + if (!init_device(&ctx, *p, grab)) { goto out; + } } if (with_libinput && !init_libinput(&ctx)) @@ -2831,6 +2818,7 @@ main(int argc, char **argv) rc = mainloop(&ctx); out: + strv_free(paths); list_for_each_safe(d, &ctx.devices, link) { if (d->device) libinput_device_unref(d->device); -- 2.7.4