|  |  |  | @ -311,6 +311,95 @@ bool load_main_config(const char *file, bool is_active) { | 
			
		
	
		
			
				
					|  |  |  |  | 	return success; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 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; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	char *full_path = strdup(path); | 
			
		
	
		
			
				
					|  |  |  |  | 	int len = strlen(path); | 
			
		
	
		
			
				
					|  |  |  |  | 	if (len >= 1 && path[0] != '/') { | 
			
		
	
		
			
				
					|  |  |  |  | 		len = len + strlen(parent_dir) + 2; | 
			
		
	
		
			
				
					|  |  |  |  | 		full_path = malloc(len * sizeof(char)); | 
			
		
	
		
			
				
					|  |  |  |  | 		if (!full_path) { | 
			
		
	
		
			
				
					|  |  |  |  | 			sway_log(L_ERROR, "Unable to allocate full path to included config"); | 
			
		
	
		
			
				
					|  |  |  |  | 			return false; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 		snprintf(full_path, len, "%s/%s", parent_dir, path); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	char *real_path = realpath(full_path, NULL); | 
			
		
	
		
			
				
					|  |  |  |  | 	free(full_path); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (real_path == NULL) { | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_log(L_DEBUG, "%s not found.", path); | 
			
		
	
		
			
				
					|  |  |  |  | 		return false; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// 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) { | 
			
		
	
		
			
				
					|  |  |  |  | 			sway_log(L_DEBUG, "%s already included once, won't be included again.", real_path); | 
			
		
	
		
			
				
					|  |  |  |  | 			free(real_path); | 
			
		
	
		
			
				
					|  |  |  |  | 			return false; | 
			
		
	
		
			
				
					|  |  |  |  | 		} | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	config->current_config = 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; | 
			
		
	
		
			
				
					|  |  |  |  | 		list_del(config->config_chain, index); | 
			
		
	
		
			
				
					|  |  |  |  | 		return false; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// restore current_config
 | 
			
		
	
		
			
				
					|  |  |  |  | 	config->current_config = 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); | 
			
		
	
		
			
				
					|  |  |  |  | 	const char *parent_dir = dirname(parent_path); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (chdir(parent_dir) < 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		free(parent_path); | 
			
		
	
		
			
				
					|  |  |  |  | 		free(wd); | 
			
		
	
		
			
				
					|  |  |  |  | 		return false; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	wordexp_t p; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (wordexp(path, &p, 0) < 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		free(parent_path); | 
			
		
	
		
			
				
					|  |  |  |  | 		free(wd); | 
			
		
	
		
			
				
					|  |  |  |  | 		return false; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	char **w = p.we_wordv; | 
			
		
	
		
			
				
					|  |  |  |  | 	size_t i; | 
			
		
	
		
			
				
					|  |  |  |  | 	for (i = 0; i < p.we_wordc; ++i) { | 
			
		
	
		
			
				
					|  |  |  |  | 		load_include_config(w[i], parent_dir, config); | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 	free(parent_path); | 
			
		
	
		
			
				
					|  |  |  |  | 	wordfree(&p); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	// restore wd
 | 
			
		
	
		
			
				
					|  |  |  |  | 	if (chdir(wd) < 0) { | 
			
		
	
		
			
				
					|  |  |  |  | 		free(wd); | 
			
		
	
		
			
				
					|  |  |  |  | 		sway_log(L_ERROR, "failed to restore working directory"); | 
			
		
	
		
			
				
					|  |  |  |  | 		return false; | 
			
		
	
		
			
				
					|  |  |  |  | 	} | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 	free(wd); | 
			
		
	
		
			
				
					|  |  |  |  | 	return true; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | bool read_config(FILE *file, struct sway_config *config) { | 
			
		
	
		
			
				
					|  |  |  |  | 	bool success = true; | 
			
		
	
		
			
				
					|  |  |  |  | 	enum cmd_status block = CMD_BLOCK_END; | 
			
		
	
	
		
			
				
					|  |  |  | 
 |