mirror of
https://github.com/swaywm/sway.git
synced 2025-01-30 12:46:43 +00:00
ipc: return all included configs in GET_CONFIG
The corresponding i3 feature[1] was added in i3 4.20. `variable_replaced_contents` is not implemented, because Sway does variable substitutions differently and it's much harder to obtain a copy of the config data with substitutions. Fixes: #5559 [1]: https://github.com/i3/i3/pull/4528
This commit is contained in:
parent
646019cad9
commit
694165b551
|
@ -481,6 +481,11 @@ enum xwayland_mode {
|
|||
XWAYLAND_MODE_IMMEDIATE,
|
||||
};
|
||||
|
||||
struct sway_config_file {
|
||||
const char *data;
|
||||
const char *path;
|
||||
};
|
||||
|
||||
/**
|
||||
* The configuration struct. The result of loading a config file.
|
||||
*/
|
||||
|
@ -550,10 +555,9 @@ struct sway_config {
|
|||
int gaps_inner;
|
||||
struct side_gaps gaps_outer;
|
||||
|
||||
list_t *config_chain;
|
||||
list_t *config_chain; /* list of struct sway_config_file* */
|
||||
bool user_config_path;
|
||||
const char *current_config_path;
|
||||
const char *current_config;
|
||||
struct sway_config_file *current_config;
|
||||
int current_config_line_number;
|
||||
char *current_config_line;
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@ struct cmd_results *output_cmd_background(int argc, char **argv) {
|
|||
if (config->reading && *src != '/') {
|
||||
// src file is inside configuration dir
|
||||
|
||||
char *conf = strdup(config->current_config_path);
|
||||
char *conf = strdup(config->current_config->path);
|
||||
if (!conf) {
|
||||
sway_log(SWAY_ERROR, "Failed to duplicate string");
|
||||
free(src);
|
||||
|
|
|
@ -22,7 +22,7 @@ static void do_reload(void *data) {
|
|||
|
||||
const char *path = NULL;
|
||||
if (config->user_config_path) {
|
||||
path = config->current_config_path;
|
||||
path = config->current_config->path;
|
||||
}
|
||||
|
||||
if (!load_main_config(path, true, false)) {
|
||||
|
@ -59,7 +59,7 @@ struct cmd_results *cmd_reload(int argc, char **argv) {
|
|||
|
||||
const char *path = NULL;
|
||||
if (config->user_config_path) {
|
||||
path = config->current_config_path;
|
||||
path = config->current_config->path;
|
||||
}
|
||||
|
||||
if (!load_main_config(path, true, true)) {
|
||||
|
|
117
sway/config.c
117
sway/config.c
|
@ -99,6 +99,15 @@ static void free_mode(struct sway_mode *mode) {
|
|||
free(mode);
|
||||
}
|
||||
|
||||
static void free_config_file(struct sway_config_file *config_file) {
|
||||
if (!config_file) {
|
||||
return;
|
||||
}
|
||||
free((char *)config_file->data);
|
||||
free((char *)config_file->path);
|
||||
free(config_file);
|
||||
}
|
||||
|
||||
void free_config(struct sway_config *config) {
|
||||
if (!config) {
|
||||
return;
|
||||
|
@ -165,9 +174,14 @@ void free_config(struct sway_config *config) {
|
|||
}
|
||||
list_free(config->criteria);
|
||||
}
|
||||
if (config->config_chain) {
|
||||
for (int i = 0; i < config->config_chain->length; ++i) {
|
||||
free_config_file(config->config_chain->items[i]);
|
||||
}
|
||||
list_free(config->config_chain);
|
||||
}
|
||||
list_free(config->no_focus);
|
||||
list_free(config->active_bar_modifiers);
|
||||
list_free_items_and_destroy(config->config_chain);
|
||||
free(config->floating_scroll_up_cmd);
|
||||
free(config->floating_scroll_down_cmd);
|
||||
free(config->floating_scroll_left_cmd);
|
||||
|
@ -175,8 +189,6 @@ void free_config(struct sway_config *config) {
|
|||
free(config->font);
|
||||
free(config->swaybg_command);
|
||||
free(config->swaynag_command);
|
||||
free((char *)config->current_config_path);
|
||||
free((char *)config->current_config);
|
||||
keysym_translation_state_destroy(config->keysym_translation_state);
|
||||
free(config);
|
||||
}
|
||||
|
@ -295,7 +307,6 @@ static void config_defaults(struct sway_config *config) {
|
|||
if (!(config->swaybg_command = strdup("swaybg"))) goto cleanup;
|
||||
|
||||
if (!(config->config_chain = create_list())) goto cleanup;
|
||||
config->current_config_path = NULL;
|
||||
config->current_config = NULL;
|
||||
|
||||
// borders
|
||||
|
@ -411,24 +422,24 @@ static char *get_config_path(void) {
|
|||
return path;
|
||||
}
|
||||
|
||||
static bool load_config(const char *path, struct sway_config *config,
|
||||
struct swaynag_instance *swaynag) {
|
||||
if (path == NULL) {
|
||||
static bool load_config(struct sway_config_file *cf,
|
||||
struct sway_config *config, struct swaynag_instance *swaynag) {
|
||||
if (cf->path == NULL) {
|
||||
sway_log(SWAY_ERROR, "Unable to find a config file!");
|
||||
return false;
|
||||
}
|
||||
|
||||
sway_log(SWAY_INFO, "Loading config from %s", path);
|
||||
sway_log(SWAY_INFO, "Loading config from %s", cf->path);
|
||||
|
||||
struct stat sb;
|
||||
if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
||||
sway_log(SWAY_ERROR, "%s is a directory not a config file", path);
|
||||
if (stat(cf->path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
|
||||
sway_log(SWAY_ERROR, "%s is a directory not a config file", cf->path);
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE *f = fopen(path, "r");
|
||||
FILE *f = fopen(cf->path, "r");
|
||||
if (!f) {
|
||||
sway_log(SWAY_ERROR, "Unable to open %s for reading", path);
|
||||
sway_log(SWAY_ERROR, "Unable to open %s for reading", cf->path);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -498,13 +509,15 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
}
|
||||
}
|
||||
|
||||
config->current_config = malloc(sizeof(struct sway_config_file));
|
||||
config->current_config->path = real_path;
|
||||
config->user_config_path = file ? true : false;
|
||||
config->current_config_path = path;
|
||||
list_add(config->config_chain, real_path);
|
||||
list_add(config->config_chain, config->current_config);
|
||||
|
||||
config->reading = true;
|
||||
|
||||
bool success = load_config(path, config, &config->swaynag_config_errors);
|
||||
bool success = load_config(config->current_config, config,
|
||||
&config->swaynag_config_errors);
|
||||
|
||||
if (validating) {
|
||||
free_config(config);
|
||||
|
@ -552,7 +565,7 @@ bool load_main_config(const char *file, bool is_active, bool validating) {
|
|||
static bool load_include_config(const char *path, const char *parent_dir,
|
||||
struct sway_config *config, struct swaynag_instance *swaynag) {
|
||||
// save parent config
|
||||
const char *parent_config = config->current_config_path;
|
||||
struct sway_config_file *parent_config = config->current_config;
|
||||
|
||||
char *full_path;
|
||||
int len = strlen(path);
|
||||
|
@ -580,8 +593,8 @@ static bool load_include_config(const char *path, const char *parent_dir,
|
|||
// check if config has already been included
|
||||
int j;
|
||||
for (j = 0; j < config->config_chain->length; ++j) {
|
||||
char *old_path = config->config_chain->items[j];
|
||||
if (strcmp(real_path, old_path) == 0) {
|
||||
struct sway_config_file *old = config->config_chain->items[j];
|
||||
if (strcmp(real_path, old->path) == 0) {
|
||||
sway_log(SWAY_DEBUG,
|
||||
"%s already included once, won't be included again.",
|
||||
real_path);
|
||||
|
@ -590,26 +603,27 @@ static bool load_include_config(const char *path, const char *parent_dir,
|
|||
}
|
||||
}
|
||||
|
||||
config->current_config_path = real_path;
|
||||
list_add(config->config_chain, real_path);
|
||||
config->current_config = calloc(1, sizeof(struct sway_config_file));
|
||||
config->current_config->path = real_path;
|
||||
list_add(config->config_chain, config->current_config);
|
||||
int index = config->config_chain->length - 1;
|
||||
|
||||
if (!load_config(real_path, config, swaynag)) {
|
||||
free(real_path);
|
||||
config->current_config_path = parent_config;
|
||||
if (!load_config(config->current_config, config, swaynag)) {
|
||||
free_config_file(config->current_config);
|
||||
config->current_config = parent_config;
|
||||
list_del(config->config_chain, index);
|
||||
return false;
|
||||
}
|
||||
|
||||
// restore current_config_path
|
||||
config->current_config_path = parent_config;
|
||||
// restore current_config
|
||||
config->current_config = parent_config;
|
||||
return true;
|
||||
}
|
||||
|
||||
void load_include_configs(const char *path, struct sway_config *config,
|
||||
struct swaynag_instance *swaynag) {
|
||||
char *wd = getcwd(NULL, 0);
|
||||
char *parent_path = strdup(config->current_config_path);
|
||||
char *parent_path = strdup(config->current_config->path);
|
||||
const char *parent_dir = dirname(parent_path);
|
||||
|
||||
if (chdir(parent_dir) < 0) {
|
||||
|
@ -744,27 +758,24 @@ static char *expand_line(const char *block, const char *line, bool add_brace) {
|
|||
|
||||
bool read_config(FILE *file, struct sway_config *config,
|
||||
struct swaynag_instance *swaynag) {
|
||||
bool reading_main_config = false;
|
||||
char *this_config = NULL;
|
||||
size_t config_size = 0;
|
||||
if (config->current_config == NULL) {
|
||||
reading_main_config = true;
|
||||
int fd = fileno(file);
|
||||
struct stat sb;
|
||||
|
||||
int ret_seek = fseek(file, 0, SEEK_END);
|
||||
long ret_tell = ftell(file);
|
||||
if (ret_seek == -1 || ret_tell == -1) {
|
||||
sway_log(SWAY_ERROR, "Unable to get size of config file");
|
||||
return false;
|
||||
}
|
||||
config_size = ret_tell;
|
||||
rewind(file);
|
||||
|
||||
config->current_config = this_config = calloc(1, config_size + 1);
|
||||
if (this_config == NULL) {
|
||||
sway_log(SWAY_ERROR, "Unable to allocate buffer for config contents");
|
||||
return false;
|
||||
}
|
||||
if (fd == -1 || fstat(fd, &sb) == -1) {
|
||||
sway_log(SWAY_ERROR, "Unable to get size of config file");
|
||||
return false;
|
||||
}
|
||||
config->current_config->data = this_config = calloc(1, sb.st_size + 1);
|
||||
if (this_config == NULL) {
|
||||
sway_log(SWAY_ERROR, "Unable to allocate buffer for config contents");
|
||||
return false;
|
||||
}
|
||||
if (fread(this_config, 1, sb.st_size, file) != (size_t)sb.st_size) {
|
||||
sway_log(SWAY_ERROR, "Config file read error");
|
||||
return false;
|
||||
}
|
||||
rewind(file);
|
||||
|
||||
bool success = true;
|
||||
int line_number = 0;
|
||||
|
@ -772,20 +783,8 @@ bool read_config(FILE *file, struct sway_config *config,
|
|||
size_t line_size = 0;
|
||||
ssize_t nread;
|
||||
list_t *stack = create_list();
|
||||
size_t read = 0;
|
||||
int nlines = 0;
|
||||
while ((nread = getline_with_cont(&line, &line_size, file, &nlines)) != -1) {
|
||||
if (reading_main_config) {
|
||||
if (read + nread > config_size) {
|
||||
sway_log(SWAY_ERROR, "Config file changed during reading");
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(&this_config[read], line);
|
||||
read += nread;
|
||||
}
|
||||
|
||||
if (line[nread - 1] == '\n') {
|
||||
line[nread - 1] = '\0';
|
||||
}
|
||||
|
@ -825,11 +824,11 @@ bool read_config(FILE *file, struct sway_config *config,
|
|||
case CMD_FAILURE:
|
||||
case CMD_INVALID:
|
||||
sway_log(SWAY_ERROR, "Error on line %i '%s': %s (%s)", line_number,
|
||||
line, res->error, config->current_config_path);
|
||||
line, res->error, config->current_config->path);
|
||||
if (!config->validating) {
|
||||
swaynag_log(config->swaynag_command, swaynag,
|
||||
"Error on line %i (%s) '%s': %s", line_number,
|
||||
config->current_config_path, line, res->error);
|
||||
config->current_config->path, line, res->error);
|
||||
}
|
||||
success = false;
|
||||
break;
|
||||
|
@ -893,7 +892,7 @@ void config_add_swaynag_warning(char *fmt, ...) {
|
|||
|
||||
swaynag_log(config->swaynag_command, &config->swaynag_config_errors,
|
||||
"Warning on line %i (%s) '%s': %s",
|
||||
config->current_config_line_number, config->current_config_path,
|
||||
config->current_config_line_number, config->current_config->path,
|
||||
config->current_config_line, str);
|
||||
|
||||
free(str);
|
||||
|
|
|
@ -231,7 +231,7 @@ json_object *ipc_json_get_version(void) {
|
|||
json_object_object_add(version, "major", json_object_new_int(major));
|
||||
json_object_object_add(version, "minor", json_object_new_int(minor));
|
||||
json_object_object_add(version, "patch", json_object_new_int(patch));
|
||||
json_object_object_add(version, "loaded_config_file_name", json_object_new_string(config->current_config_path));
|
||||
json_object_object_add(version, "loaded_config_file_name", json_object_new_string(config->current_config->path));
|
||||
|
||||
return version;
|
||||
}
|
||||
|
|
|
@ -901,7 +901,20 @@ void ipc_client_handle_command(struct ipc_client *client, uint32_t payload_lengt
|
|||
case IPC_GET_CONFIG:
|
||||
{
|
||||
json_object *json = json_object_new_object();
|
||||
json_object_object_add(json, "config", json_object_new_string(config->current_config));
|
||||
json_object_object_add(json, "config",
|
||||
json_object_new_string(config->current_config->data));
|
||||
json_object *includes =
|
||||
json_object_new_array_ext(config->config_chain->length);
|
||||
for (int i = 0; i < config->config_chain->length; ++i) {
|
||||
struct sway_config_file *cf = config->config_chain->items[i];
|
||||
json_object *include = json_object_new_object();
|
||||
json_object_object_add(include, "path",
|
||||
json_object_new_string(cf->path));
|
||||
json_object_object_add(include, "raw_contents",
|
||||
json_object_new_string(cf->data));
|
||||
json_object_array_add(includes, include);
|
||||
}
|
||||
json_object_object_add(json, "included_configs", includes);
|
||||
const char *json_string = json_object_to_json_string(json);
|
||||
ipc_send_reply(client, payload_type, json_string,
|
||||
(uint32_t)strlen(json_string));
|
||||
|
|
Loading…
Reference in a new issue