output/background: fix config ignoring fallback color

currently, the output background command handler prematurely
returns with an error if the background file cannot be accessed.
It should only error if user did not provide fallback color.

closes #8556

Changes

- Introduce variables to avoid uneccessary writing on output members
- Log a debug message when fallback is being used over inaccessible
   file
- Always parse the background color and swaynag warn if it is incorrect

- when updating output member variables, free previous values
- add cleanup label and goto it if `strdup` fails
- Move output->member initializations to before parsing fallback, Also
free and init output->background as well
This commit is contained in:
Furkan Sahin 2025-02-03 13:13:48 -05:00 committed by Simon Ser
parent 851b8c6fb6
commit 4852087e61

View file

@ -3,10 +3,8 @@
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include <unistd.h> #include <unistd.h>
#include <errno.h>
#include "sway/commands.h" #include "sway/commands.h"
#include "sway/config.h" #include "sway/config.h"
#include "sway/swaynag.h"
#include "log.h" #include "log.h"
#include "stringop.h" #include "stringop.h"
@ -42,14 +40,14 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
} }
struct output_config *output = config->handler_context.output_config; struct output_config *output = config->handler_context.output_config;
char *src = NULL;
if (strcasecmp(argv[1], "solid_color") == 0) { if (strcasecmp(argv[1], "solid_color") == 0) {
if (!validate_color(argv[0])) { if (!validate_color(argv[0])) {
return cmd_results_new(CMD_INVALID, return cmd_results_new(CMD_INVALID,
"Colors should be of the form #RRGGBB"); "Colors should be of the form #RRGGBB");
} }
output->background = strdup(argv[0]); if (!(output->background = strdup(argv[0]))) goto cleanup;
output->background_option = strdup("solid_color"); if (!(output->background_option = strdup("solid_color"))) goto cleanup;
output->background_fallback = NULL; output->background_fallback = NULL;
argc -= 2; argv += 2; argc -= 2; argv += 2;
} else { } else {
@ -77,37 +75,25 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
return cmd_results_new(CMD_INVALID, "Missing background file"); return cmd_results_new(CMD_INVALID, "Missing background file");
} }
char *src = join_args(argv, j); if (!(src = join_args(argv, j))) goto cleanup;
if (!expand_path(&src)) { if (!expand_path(&src)) {
struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID, struct cmd_results *cmd_res = cmd_results_new(CMD_INVALID,
"Invalid syntax (%s)", src); "Invalid syntax (%s)", src);
free(src); free(src);
return cmd_res; return cmd_res;
} }
if (!src) {
sway_log(SWAY_ERROR, "Failed to allocate expanded path");
return cmd_results_new(CMD_FAILURE, "Unable to allocate resource");
}
if (config->reading && *src != '/') { if (config->reading && *src != '/') {
// src file is inside configuration dir // src file is inside configuration dir
char *conf = strdup(config->current_config_path); char *conf = strdup(config->current_config_path);
if (!conf) { if (!conf) goto cleanup;
sway_log(SWAY_ERROR, "Failed to duplicate string");
free(src);
return cmd_results_new(CMD_FAILURE,
"Unable to allocate resources");
}
char *conf_path = dirname(conf); char *conf_path = dirname(conf);
char *real_src = malloc(strlen(conf_path) + strlen(src) + 2); char *real_src = malloc(strlen(conf_path) + strlen(src) + 2);
if (!real_src) { if (!real_src) {
free(src);
free(conf); free(conf);
sway_log(SWAY_ERROR, "Unable to allocate memory"); goto cleanup;
return cmd_results_new(CMD_FAILURE,
"Unable to allocate resources");
} }
snprintf(real_src, strlen(conf_path) + strlen(src) + 2, "%s/%s", conf_path, src); snprintf(real_src, strlen(conf_path) + strlen(src) + 2, "%s/%s", conf_path, src);
@ -117,40 +103,48 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
} }
bool can_access = access(src, F_OK) != -1; bool can_access = access(src, F_OK) != -1;
argc -= j + 1; argv += j + 1;
free(output->background_option);
free(output->background_fallback);
free(output->background);
output->background = output->background_option = output->background_fallback = NULL;
char *fallback = NULL;
if (argc && *argv[0] == '#') {
if (validate_color(argv[0])) {
if (!(fallback = strdup(argv[0]))) goto cleanup;
output->background_fallback = fallback;
} else {
sway_log(SWAY_ERROR, "fallback '%s' should be of the form #RRGGBB", argv[0]);
config_add_swaynag_warning("fallback '%s' should be of the form #RRGGBB\n", argv[0]);
}
argc--; argv++;
}
if (!can_access) { if (!can_access) {
sway_log_errno(SWAY_ERROR, "Unable to access background file '%s'", if (!fallback) {
src); sway_log(SWAY_ERROR, "Unable to access background file '%s' "
config_add_swaynag_warning("Unable to access background file '%s'", "and no valid fallback provided", src);
src); struct cmd_results *res = cmd_results_new(CMD_FAILURE, "Unable to access "
struct cmd_results *result = cmd_results_new(CMD_FAILURE, "background file '%s' and no valid fallback provided", src);
"unable to access background file '%s'", src); free(src);
free(src); return res;
return result; }
sway_log(SWAY_DEBUG, "Cannot access file '%s', using fallback '%s'", src, fallback);
output->background = fallback;
if (!(output->background_option = strdup("solid_color"))) goto cleanup;
output->background_fallback = NULL;
} else { } else {
output->background = src; output->background = src;
output->background_option = strdup(mode); if (!(output->background_option = strdup(mode))) goto cleanup;
}
argc -= j + 1; argv += j + 1;
output->background_fallback = NULL;
if (argc && *argv[0] == '#') {
if (!validate_color(argv[0])) {
return cmd_results_new(CMD_INVALID,
"fallback color should be of the form #RRGGBB");
}
output->background_fallback = strdup(argv[0]);
argc--; argv++;
if (!can_access) {
output->background = output->background_fallback;
output->background_option = strdup("solid_color");
output->background_fallback = NULL;
}
} }
} }
config->handler_context.leftovers.argc = argc; config->handler_context.leftovers.argc = argc;
config->handler_context.leftovers.argv = argv; config->handler_context.leftovers.argv = argv;
return NULL; return NULL;
cleanup:
free(src);
sway_log(SWAY_ERROR, "Failed to allocate resources");
return cmd_results_new(CMD_FAILURE, "Unable to allocate resources");
} }