diff --git a/include/ipc.h b/include/ipc.h index c9c5b1cd..6f6795b3 100644 --- a/include/ipc.h +++ b/include/ipc.h @@ -14,6 +14,7 @@ enum ipc_command_type { IPC_GET_BAR_CONFIG = 6, IPC_GET_VERSION = 7, IPC_GET_BINDING_MODES = 8, + IPC_GET_CONFIG = 9, // sway-specific command types IPC_GET_INPUTS = 100, diff --git a/include/sway/config.h b/include/sway/config.h index ac668c24..d5e4116f 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -341,6 +341,7 @@ struct sway_config { int gaps_outer; list_t *config_chain; + const char *current_config_path; const char *current_config; enum sway_container_border border; @@ -496,7 +497,4 @@ void config_update_font_height(bool recalculate); /* Global config singleton. */ extern struct sway_config *config; -/* Config file currently being read */ -extern const char *current_config_path; - #endif diff --git a/sway/commands/output/background.c b/sway/commands/output/background.c index c2c138f8..4ed56c2a 100644 --- a/sway/commands/output/background.c +++ b/sway/commands/output/background.c @@ -80,7 +80,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); + char *conf = strdup(config->current_config_path); if (!conf) { wlr_log(WLR_ERROR, "Failed to duplicate string"); free(src); diff --git a/sway/commands/reload.c b/sway/commands/reload.c index 9fc213c4..c6715f9c 100644 --- a/sway/commands/reload.c +++ b/sway/commands/reload.c @@ -7,7 +7,7 @@ struct cmd_results *cmd_reload(int argc, char **argv) { if ((error = checkarg(argc, "reload", EXPECTED_EQUAL_TO, 0))) { return error; } - if (!load_main_config(config->current_config, true)) { + if (!load_main_config(config->current_config_path, true)) { return cmd_results_new(CMD_FAILURE, "reload", "Error(s) reloading config."); } diff --git a/sway/config.c b/sway/config.c index d0e0e432..c59f4f0d 100644 --- a/sway/config.c +++ b/sway/config.c @@ -117,6 +117,7 @@ void free_config(struct sway_config *config) { free(config->floating_scroll_left_cmd); free(config->floating_scroll_right_cmd); free(config->font); + free((char *)config->current_config_path); free((char *)config->current_config); free(config); } @@ -205,6 +206,7 @@ static void config_defaults(struct sway_config *config) { if (!(config->active_bar_modifiers = create_list())) goto cleanup; if (!(config->config_chain = create_list())) goto cleanup; + config->current_config_path = NULL; config->current_config = NULL; // borders @@ -304,8 +306,6 @@ static char *get_config_path(void) { return NULL; // Not reached } -const char *current_config_path; - static bool load_config(const char *path, struct sway_config *config) { if (path == NULL) { wlr_log(WLR_ERROR, "Unable to find a config file!"); @@ -313,7 +313,6 @@ static bool load_config(const char *path, struct sway_config *config) { } wlr_log(WLR_INFO, "Loading config from %s", path); - current_config_path = path; struct stat sb; if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { @@ -333,7 +332,6 @@ static bool load_config(const char *path, struct sway_config *config) { wlr_log(WLR_ERROR, "Error(s) loading config!"); } - current_config_path = NULL; return true; } @@ -358,7 +356,7 @@ bool load_main_config(const char *file, bool is_active) { config->active = true; } - config->current_config = path; + config->current_config_path = path; list_add(config->config_chain, path); config->reading = true; @@ -428,7 +426,7 @@ bool load_main_config(const char *file, bool is_active) { static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) { // save parent config - const char *parent_config = config->current_config; + const char *parent_config = config->current_config_path; char *full_path; int len = strlen(path); @@ -466,25 +464,25 @@ static bool load_include_config(const char *path, const char *parent_dir, } } - config->current_config = real_path; + config->current_config_path = real_path; list_add(config->config_chain, real_path); int index = config->config_chain->length - 1; if (!load_config(real_path, config)) { free(real_path); - config->current_config = parent_config; + config->current_config_path = parent_config; list_del(config->config_chain, index); return false; } - // restore current_config - config->current_config = parent_config; + // restore current_config_path + config->current_config_path = parent_config; return true; } bool load_include_configs(const char *path, struct sway_config *config) { char *wd = getcwd(NULL, 0); - char *parent_path = strdup(config->current_config); + char *parent_path = strdup(config->current_config_path); const char *parent_dir = dirname(parent_path); if (chdir(parent_dir) < 0) { @@ -561,6 +559,23 @@ static char *expand_line(const char *block, const char *line, bool add_brace) { } bool read_config(FILE *file, struct sway_config *config) { + bool reading_main_config = false; + char *current_config, *config_pos; + long config_size = 0; + if (config->current_config == NULL) { + reading_main_config = true; + + fseek(file, 0, SEEK_END); + config_size = ftell(file); + rewind(file); + + config_pos = current_config = malloc(config_size + 1); + if (current_config == NULL) { + wlr_log(WLR_ERROR, "Unable to allocate buffer for config contents"); + return false; + } + } + bool success = true; int line_number = 0; char *line; @@ -573,6 +588,14 @@ bool read_config(FILE *file, struct sway_config *config) { } line_number++; wlr_log(WLR_DEBUG, "Read line %d: %s", line_number, line); + + if (reading_main_config) { + size_t l = strlen(line); + memcpy(config_pos, line, l); // don't copy terminating character + config_pos += l; + *config_pos++ = '\n'; + } + line = strip_whitespace(line); if (line[0] == '#') { free(line); @@ -592,6 +615,8 @@ bool read_config(FILE *file, struct sway_config *config) { if (!expanded) { list_foreach(stack, free); list_free(stack); + free(line); + free(current_config); return false; } wlr_log(WLR_DEBUG, "Expanded line: %s", expanded); @@ -607,7 +632,7 @@ bool read_config(FILE *file, struct sway_config *config) { case CMD_FAILURE: case CMD_INVALID: wlr_log(WLR_ERROR, "Error on line %i '%s': %s (%s)", line_number, - line, res->error, config->current_config); + line, res->error, config->current_config_path); success = false; break; @@ -652,6 +677,10 @@ bool read_config(FILE *file, struct sway_config *config) { list_foreach(stack, free); list_free(stack); + if (reading_main_config) { + current_config[config_size - 1] = '\0'; + config->current_config = current_config; + } return success; } diff --git a/sway/ipc-json.c b/sway/ipc-json.c index b9289e25..3d0e88f0 100644 --- a/sway/ipc-json.c +++ b/sway/ipc-json.c @@ -2,6 +2,7 @@ #include #include #include "log.h" +#include "sway/config.h" #include "sway/ipc-json.h" #include "sway/tree/container.h" #include "sway/tree/workspace.h" @@ -41,6 +42,7 @@ json_object *ipc_json_get_version() { 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)); return version; } diff --git a/sway/ipc-server.c b/sway/ipc-server.c index 70a4141e..c5161a6b 100644 --- a/sway/ipc-server.c +++ b/sway/ipc-server.c @@ -17,6 +17,7 @@ #include #include #include "sway/commands.h" +#include "sway/config.h" #include "sway/ipc-json.h" #include "sway/ipc-server.h" #include "sway/output.h" @@ -681,6 +682,17 @@ void ipc_client_handle_command(struct ipc_client *client) { goto exit_cleanup; } + case IPC_GET_CONFIG: + { + json_object *json = json_object_new_object(); + json_object_object_add(json, "config", json_object_new_string(config->current_config)); + const char *json_string = json_object_to_json_string(json); + client_valid = + ipc_send_reply(client, json_string, (uint32_t)strlen(json_string)); + json_object_put(json); // free + goto exit_cleanup; + } + default: wlr_log(WLR_INFO, "Unknown IPC command type %i", client->current_command); goto exit_cleanup; diff --git a/swaymsg/main.c b/swaymsg/main.c index 42e488f3..4c068f69 100644 --- a/swaymsg/main.c +++ b/swaymsg/main.c @@ -240,6 +240,12 @@ static void pretty_print_version(json_object *v) { printf("sway version %s\n", json_object_get_string(ver)); } +static void pretty_print_config(json_object *c) { + json_object *config; + json_object_object_get_ex(c, "config", &config); + printf("%s\n", json_object_get_string(config)); +} + static void pretty_print_clipboard(json_object *v) { if (success(v, true)) { if (json_object_is_type(v, json_type_array)) { @@ -277,7 +283,7 @@ static void pretty_print(int type, json_object *resp) { if (type != IPC_COMMAND && type != IPC_GET_WORKSPACES && type != IPC_GET_INPUTS && type != IPC_GET_OUTPUTS && type != IPC_GET_VERSION && type != IPC_GET_CLIPBOARD && - type != IPC_GET_SEATS) { + type != IPC_GET_SEATS && type != IPC_GET_CONFIG) { printf("%s\n", json_object_to_json_string_ext(resp, JSON_C_TO_STRING_PRETTY | JSON_C_TO_STRING_SPACED)); return; @@ -288,6 +294,11 @@ static void pretty_print(int type, json_object *resp) { return; } + if (type == IPC_GET_CONFIG) { + pretty_print_config(resp); + return; + } + if (type == IPC_GET_CLIPBOARD) { pretty_print_clipboard(resp); return; @@ -409,6 +420,8 @@ int main(int argc, char **argv) { type = IPC_GET_VERSION; } else if (strcasecmp(cmdtype, "get_binding_modes") == 0) { type = IPC_GET_BINDING_MODES; + } else if (strcasecmp(cmdtype, "get_config") == 0) { + type = IPC_GET_CONFIG; } else if (strcasecmp(cmdtype, "get_clipboard") == 0) { type = IPC_GET_CLIPBOARD; } else { diff --git a/swaymsg/swaymsg.1.scd b/swaymsg/swaymsg.1.scd index f9b600b9..59a706d4 100644 --- a/swaymsg/swaymsg.1.scd +++ b/swaymsg/swaymsg.1.scd @@ -62,6 +62,9 @@ _swaymsg_ [options...] [message] *get\_binding\_modes* Gets a JSON-encoded list of currently configured binding modes. +*get\_config* + Gets a JSON-encoded copy of the current configuration. + *get\_clipboard* Get JSON-encoded information about the clipboard. Returns the current clipboard mime-types if called without