diff options
Diffstat (limited to 'sway/config.c')
-rw-r--r-- | sway/config.c | 155 |
1 files changed, 123 insertions, 32 deletions
diff --git a/sway/config.c b/sway/config.c index a5fdf850..c30c1767 100644 --- a/sway/config.c +++ b/sway/config.c | |||
@@ -2,6 +2,7 @@ | |||
2 | #include <stdbool.h> | 2 | #include <stdbool.h> |
3 | #include <stdlib.h> | 3 | #include <stdlib.h> |
4 | #include <unistd.h> | 4 | #include <unistd.h> |
5 | #include <libgen.h> | ||
5 | #include <wordexp.h> | 6 | #include <wordexp.h> |
6 | #include <sys/types.h> | 7 | #include <sys/types.h> |
7 | #include <sys/wait.h> | 8 | #include <sys/wait.h> |
@@ -126,6 +127,7 @@ void free_config(struct sway_config *config) { | |||
126 | list_free(config->output_configs); | 127 | list_free(config->output_configs); |
127 | 128 | ||
128 | list_free(config->active_bar_modifiers); | 129 | list_free(config->active_bar_modifiers); |
130 | free_flat_list(config->config_chain); | ||
129 | free(config->font); | 131 | free(config->font); |
130 | free(config); | 132 | free(config); |
131 | } | 133 | } |
@@ -175,6 +177,9 @@ static void config_defaults(struct sway_config *config) { | |||
175 | config->gaps_outer = 0; | 177 | config->gaps_outer = 0; |
176 | 178 | ||
177 | config->active_bar_modifiers = create_list(); | 179 | config->active_bar_modifiers = create_list(); |
180 | |||
181 | config->config_chain = create_list(); | ||
182 | config->current_config = NULL; | ||
178 | } | 183 | } |
179 | 184 | ||
180 | static int compare_modifiers(const void *left, const void *right) { | 185 | static int compare_modifiers(const void *left, const void *right) { |
@@ -237,16 +242,7 @@ static char *get_config_path(void) { | |||
237 | return NULL; // Not reached | 242 | return NULL; // Not reached |
238 | } | 243 | } |
239 | 244 | ||
240 | bool load_config(const char *file) { | 245 | static bool load_config(const char *path, struct sway_config *config) { |
241 | input_init(); | ||
242 | |||
243 | char *path; | ||
244 | if (file != NULL) { | ||
245 | path = strdup(file); | ||
246 | } else { | ||
247 | path = get_config_path(); | ||
248 | } | ||
249 | |||
250 | sway_log(L_INFO, "Loading config from %s", path); | 246 | sway_log(L_INFO, "Loading config from %s", path); |
251 | 247 | ||
252 | if (path == NULL) { | 248 | if (path == NULL) { |
@@ -257,20 +253,12 @@ bool load_config(const char *file) { | |||
257 | FILE *f = fopen(path, "r"); | 253 | FILE *f = fopen(path, "r"); |
258 | if (!f) { | 254 | if (!f) { |
259 | sway_log(L_ERROR, "Unable to open %s for reading", path); | 255 | sway_log(L_ERROR, "Unable to open %s for reading", path); |
260 | free(path); | ||
261 | return false; | 256 | return false; |
262 | } | 257 | } |
263 | free(path); | ||
264 | 258 | ||
265 | bool config_load_success; | 259 | bool config_load_success = read_config(f, config); |
266 | if (config) { | ||
267 | config_load_success = read_config(f, true); | ||
268 | } else { | ||
269 | config_load_success = read_config(f, false); | ||
270 | } | ||
271 | fclose(f); | 260 | fclose(f); |
272 | 261 | ||
273 | update_active_bar_modifiers(); | ||
274 | 262 | ||
275 | if (!config_load_success) { | 263 | if (!config_load_success) { |
276 | sway_log(L_ERROR, "Error(s) loading config!"); | 264 | sway_log(L_ERROR, "Error(s) loading config!"); |
@@ -279,17 +267,129 @@ bool load_config(const char *file) { | |||
279 | return true; | 267 | return true; |
280 | } | 268 | } |
281 | 269 | ||
282 | bool read_config(FILE *file, bool is_active) { | 270 | bool load_main_config(const char *file, bool is_active) { |
271 | input_init(); | ||
272 | |||
273 | char *path; | ||
274 | if (file != NULL) { | ||
275 | path = strdup(file); | ||
276 | } else { | ||
277 | path = get_config_path(); | ||
278 | } | ||
279 | |||
283 | struct sway_config *old_config = config; | 280 | struct sway_config *old_config = config; |
284 | config = calloc(1, sizeof(struct sway_config)); | 281 | config = calloc(1, sizeof(struct sway_config)); |
285 | 282 | ||
286 | config_defaults(config); | 283 | config_defaults(config); |
287 | config->reading = true; | ||
288 | if (is_active) { | 284 | if (is_active) { |
289 | sway_log(L_DEBUG, "Performing configuration file reload"); | 285 | sway_log(L_DEBUG, "Performing configuration file reload"); |
290 | config->reloading = true; | 286 | config->reloading = true; |
291 | config->active = true; | 287 | config->active = true; |
292 | } | 288 | } |
289 | |||
290 | config->current_config = path; | ||
291 | list_add(config->config_chain, path); | ||
292 | |||
293 | config->reading = true; | ||
294 | bool success = load_config(path, config); | ||
295 | |||
296 | if (is_active) { | ||
297 | config->reloading = false; | ||
298 | } | ||
299 | |||
300 | if (old_config) { | ||
301 | free_config(old_config); | ||
302 | } | ||
303 | config->reading = false; | ||
304 | |||
305 | if (success) { | ||
306 | update_active_bar_modifiers(); | ||
307 | } | ||
308 | |||
309 | return success; | ||
310 | } | ||
311 | |||
312 | static bool load_include_config(const char *path, const char *parent_dir, struct sway_config *config) { | ||
313 | // save parent config | ||
314 | const char *parent_config = config->current_config; | ||
315 | |||
316 | char *full_path = strdup(path); | ||
317 | int len = strlen(path); | ||
318 | if (len >= 1 && path[0] != '/') { | ||
319 | len = len + strlen(parent_dir) + 2; | ||
320 | full_path = malloc(len * sizeof(char)); | ||
321 | snprintf(full_path, len, "%s/%s", parent_dir, path); | ||
322 | } | ||
323 | |||
324 | char *real_path = realpath(full_path, NULL); | ||
325 | free(full_path); | ||
326 | |||
327 | // check if config has already been included | ||
328 | int j; | ||
329 | for (j = 0; j < config->config_chain->length; ++j) { | ||
330 | char *old_path = config->config_chain->items[j]; | ||
331 | if (strcmp(real_path, old_path) == 0) { | ||
332 | sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path); | ||
333 | free(real_path); | ||
334 | return false; | ||
335 | } | ||
336 | } | ||
337 | |||
338 | config->current_config = real_path; | ||
339 | list_add(config->config_chain, real_path); | ||
340 | int index = config->config_chain->length - 1; | ||
341 | |||
342 | if (!load_config(real_path, config)) { | ||
343 | free(real_path); | ||
344 | config->current_config = parent_config; | ||
345 | list_del(config->config_chain, index); | ||
346 | return false; | ||
347 | } | ||
348 | |||
349 | // restore current_config | ||
350 | config->current_config = parent_config; | ||
351 | return true; | ||
352 | } | ||
353 | |||
354 | bool load_include_configs(const char *path, struct sway_config *config) { | ||
355 | char *wd = getcwd(NULL, 0); | ||
356 | char *parent_path = strdup(config->current_config); | ||
357 | const char *parent_dir = dirname(parent_path); | ||
358 | |||
359 | if (chdir(parent_dir) < 0) { | ||
360 | free(parent_path); | ||
361 | free(wd); | ||
362 | return false; | ||
363 | } | ||
364 | |||
365 | wordexp_t p; | ||
366 | |||
367 | if (wordexp(path, &p, 0) < 0) { | ||
368 | free(parent_path); | ||
369 | free(wd); | ||
370 | return false; | ||
371 | } | ||
372 | |||
373 | char **w = p.we_wordv; | ||
374 | size_t i; | ||
375 | for (i = 0; i < p.we_wordc; ++i) { | ||
376 | load_include_config(w[i], parent_dir, config); | ||
377 | } | ||
378 | free(parent_path); | ||
379 | wordfree(&p); | ||
380 | |||
381 | // restore wd | ||
382 | if (chdir(wd) < 0) { | ||
383 | free(wd); | ||
384 | sway_log(L_ERROR, "failed to restore working directory"); | ||
385 | return false; | ||
386 | } | ||
387 | |||
388 | free(wd); | ||
389 | return true; | ||
390 | } | ||
391 | |||
392 | bool read_config(FILE *file, struct sway_config *config) { | ||
293 | bool success = true; | 393 | bool success = true; |
294 | enum cmd_status block = CMD_BLOCK_END; | 394 | enum cmd_status block = CMD_BLOCK_END; |
295 | 395 | ||
@@ -307,8 +407,8 @@ bool read_config(FILE *file, bool is_active) { | |||
307 | switch(res->status) { | 407 | switch(res->status) { |
308 | case CMD_FAILURE: | 408 | case CMD_FAILURE: |
309 | case CMD_INVALID: | 409 | case CMD_INVALID: |
310 | sway_log(L_ERROR, "Error on line %i '%s': %s", line_number, line, | 410 | sway_log(L_ERROR, "Error on line %i '%s': %s (%s)", line_number, line, |
311 | res->error); | 411 | res->error, config->current_config); |
312 | success = false; | 412 | success = false; |
313 | break; | 413 | break; |
314 | 414 | ||
@@ -386,15 +486,6 @@ bool read_config(FILE *file, bool is_active) { | |||
386 | free(res); | 486 | free(res); |
387 | } | 487 | } |
388 | 488 | ||
389 | if (is_active) { | ||
390 | config->reloading = false; | ||
391 | arrange_windows(&root_container, -1, -1); | ||
392 | } | ||
393 | if (old_config) { | ||
394 | free_config(old_config); | ||
395 | } | ||
396 | |||
397 | config->reading = false; | ||
398 | return success; | 489 | return success; |
399 | } | 490 | } |
400 | 491 | ||