diff --git a/common/stringop.c b/common/stringop.c index ac7df2962..0df2b33dd 100644 --- a/common/stringop.c +++ b/common/stringop.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "list.h" #include "log.h" #include "stringop.h" @@ -309,3 +310,21 @@ char *argsep(char **stringp, const char *delim, char *matched) { } return start; } + +bool expand_path(char **path) { + wordexp_t p = {0}; + while (strstr(*path, " ")) { + *path = realloc(*path, strlen(*path) + 2); + char *ptr = strstr(*path, " ") + 1; + memmove(ptr + 1, ptr, strlen(ptr) + 1); + *ptr = '\\'; + } + if (wordexp(*path, &p, 0) != 0 || p.we_wordv[0] == NULL) { + wordfree(&p); + return false; + } + free(*path); + *path = join_args(p.we_wordv, p.we_wordc); + wordfree(&p); + return true; +} diff --git a/include/stringop.h b/include/stringop.h index 2aabcee73..e3f4f0f7c 100644 --- a/include/stringop.h +++ b/include/stringop.h @@ -1,6 +1,7 @@ #ifndef _SWAY_STRINGOP_H #define _SWAY_STRINGOP_H +#include #include "list.h" void strip_whitespace(char *str); @@ -26,4 +27,7 @@ char *join_args(char **argv, int argc); // Split string into 2 by delim, handle quotes char *argsep(char **stringp, const char *delim, char *matched_delim); +// Expand a path using shell replacements such as $HOME and ~ +bool expand_path(char **path); + #endif diff --git a/sway/commands/input/xkb_file.c b/sway/commands/input/xkb_file.c index ef59bffc5..493f94fbd 100644 --- a/sway/commands/input/xkb_file.c +++ b/sway/commands/input/xkb_file.c @@ -1,7 +1,10 @@ #define _POSIX_C_SOURCE 200809L +#include +#include #include "sway/config.h" #include "sway/commands.h" #include "log.h" +#include "stringop.h" struct cmd_results *input_cmd_xkb_file(int argc, char **argv) { struct cmd_results *error = NULL; @@ -18,6 +21,25 @@ struct cmd_results *input_cmd_xkb_file(int argc, char **argv) { ic->xkb_file = NULL; } else { ic->xkb_file = strdup(argv[0]); + if (!expand_path(&ic->xkb_file)) { + error = cmd_results_new(CMD_INVALID, "Invalid syntax (%s)", + ic->xkb_file); + free(ic->xkb_file); + ic->xkb_file = NULL; + return error; + } + if (!ic->xkb_file) { + sway_log(SWAY_ERROR, "Failed to allocate expanded path"); + return cmd_results_new(CMD_FAILURE, "Unable to allocate resource"); + } + + bool can_access = access(ic->xkb_file, F_OK) != -1; + if (!can_access) { + sway_log_errno(SWAY_ERROR, "Unable to access xkb file '%s'", + ic->xkb_file); + config_add_swaynag_warning("Unable to access xkb file '%s'", + ic->xkb_file); + } } ic->xkb_file_is_set = true; diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c index 054fb707e..68ee9fe14 100644 --- a/sway/commands/output/background.c +++ b/sway/commands/output/background.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "sway/commands.h" #include "sway/config.h" @@ -79,26 +78,15 @@ struct cmd_results *output_cmd_background(int argc, char **argv) { return cmd_results_new(CMD_INVALID, "Missing background file"); } - wordexp_t p = {0}; char *src = join_args(argv, j); - while (strstr(src, " ")) { - src = realloc(src, strlen(src) + 2); - char *ptr = strstr(src, " ") + 1; - memmove(ptr + 1, ptr, strlen(ptr) + 1); - *ptr = '\\'; - } - if (wordexp(src, &p, 0) != 0 || p.we_wordv[0] == NULL) { + if (!expand_path(&src)) { struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID, "Invalid syntax (%s)", src); free(src); - wordfree(&p); return cmd_res; } - free(src); - src = join_args(p.we_wordv, p.we_wordc); - wordfree(&p); if (!src) { - sway_log(SWAY_ERROR, "Failed to duplicate string"); + sway_log(SWAY_ERROR, "Failed to allocate expanded path"); return cmd_results_new(CMD_FAILURE, "Unable to allocate resource"); }