From fa1f08a36948d4bb239bdee6fb8820e86add4f8d Mon Sep 17 00:00:00 2001 From: NiLuJe Date: Wed, 13 May 2020 03:54:43 +0200 Subject: [PATCH] Allow whitespace in cmd_spawn/cmd_output args (fixes #16) (#19) * Allow whitespace in cmd_spawn/cmd_output args * Trim cmd no matter the content of the extra option field * Don't mistake a stray colon in the actual command for a field separator * Simplified quiet option for cmd_spawn, fixed up parsing * Fixed case where option could start with, but not actually be, quiet. * Fixed restoring the original command when no option is specified. * Simplified code. * Fixed typos in comments Co-authored-by: Patrick Gaskin --- src/action_cc.cc | 22 +++++++++++++--------- src/config.c | 12 ------------ src/util.h | 13 +++++++++++++ 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/src/action_cc.cc b/src/action_cc.cc index aa943b2..7f19877 100644 --- a/src/action_cc.cc +++ b/src/action_cc.cc @@ -345,7 +345,7 @@ NM_ACTION_(power) { N3PowerWorkflowManager *(*N3PowerWorkflowManager_sharedInstance)(); reinterpret_cast(N3PowerWorkflowManager_sharedInstance) = dlsym(RTLD_DEFAULT, "_ZN22N3PowerWorkflowManager14sharedInstanceEv"); NM_ASSERT(N3PowerWorkflowManager_sharedInstance, "could not dlsym N3PowerWorkflowManager::sharedInstance, so cannot perform action cleanly (if you must, report a bug and use cmd_spawn instead)"); - + N3PowerWorkflowManager *pwm = N3PowerWorkflowManager_sharedInstance(); NM_ASSERT(pwm, "could not get shared power manager pointer"); @@ -375,13 +375,15 @@ NM_ACTION_(power) { NM_ACTION_(cmd_spawn) { #define NM_ERR_RET nullptr - char *tmp = strdup(arg); - char *cmd = tmp; - bool quiet = false; - if (!strncmp(tmp, "quiet:", 6)) { - cmd += 6; - quiet = true; - } + char *tmp = strdup(arg); // strsep and strtrim will modify it + char *tmp1 = tmp; // so we can still free tmp later + char *tmp2 = strtrim(strsep(&tmp1, ":")); // get the part before the : into tmp2, if any + + bool quiet = tmp1 && !strcmp(tmp2, "quiet"); + const char *cmd = (tmp1 && quiet) + ? strtrim(tmp1) // trim the actual command + : arg; // restore the original arg if there wasn't any option field or if it wasn't "quiet" + QProcess proc; uint64_t pid; bool ok = proc.startDetached( @@ -393,6 +395,7 @@ NM_ACTION_(cmd_spawn) { QStringLiteral("/"), (qint64*)(&pid) ); + free(tmp); NM_ASSERT(ok, "could not start process"); NM_RETURN_OK(quiet ? nm_action_result_silent() : nm_action_result_toast("Successfully started process with PID %lu.", (unsigned long)(pid))); @@ -405,8 +408,9 @@ NM_ACTION_(cmd_output) { char *tmp = strdup(arg); char *cmd = tmp; - char *tmp1 = strsep(&cmd, ":"), *tmp2; + char *tmp1 = strtrim(strsep(&cmd, ":")), *tmp2; long timeout = strtol(tmp1, &tmp2, 10); + cmd = strtrim(cmd); NM_ASSERT(*tmp1 && !*tmp2 && timeout > 0 && timeout < 10000, "invalid timeout '%s'", tmp1); QProcess proc; diff --git a/src/config.c b/src/config.c index 8efe3e3..1587437 100644 --- a/src/config.c +++ b/src/config.c @@ -1,5 +1,4 @@ #define _GNU_SOURCE // asprintf -#include #include #include #include @@ -35,17 +34,6 @@ struct nm_config_t { nm_config_t *next; }; -// strtrim trims ASCII whitespace in-place (i.e. don't give it a string literal) -// from the left/right of the string. -static char *strtrim(char *s){ - if (!s) return NULL; - char *a = s, *b = s + strlen(s); - for (; a < b && isspace((unsigned char)(*a)); a++); - for (; b > a && isspace((unsigned char)(*(b-1))); b--); - *b = '\0'; - return a; -} - static void nm_config_push_menu_item(nm_config_t **cfg, nm_menu_item_t *it) { nm_config_t *tmp = calloc(1, sizeof(nm_config_t)); tmp->type = NM_CONFIG_TYPE_MENU_ITEM; diff --git a/src/util.h b/src/util.h index 322ec27..cb7ce3c 100644 --- a/src/util.h +++ b/src/util.h @@ -8,9 +8,22 @@ extern "C" { #define _GNU_SOURCE // asprintf #endif +#include #include +#include #include +// strtrim trims ASCII whitespace in-place (i.e. don't give it a string literal) +// from the left/right of the string. +inline char *strtrim(char *s){ + if (!s) return NULL; + char *a = s, *b = s + strlen(s); + for (; a < b && isspace((unsigned char)(*a)); a++); + for (; b > a && isspace((unsigned char)(*(b-1))); b--); + *b = '\0'; + return a; +} + // A bunch of useful macros to simplify error handling and logging. // NM_LOG writes a log message.