char *workspace_next_name(void) { sway_log(L_DEBUG, "Workspace: Generating new name"); int i; int l = 1; // Scan all workspace bindings to find the next available workspace name, // if none are found/available then default to a number struct sway_mode *mode = config->current_mode; for (i = 0; i < mode->bindings->length; ++i) { struct sway_binding *binding = mode->bindings->items[i]; const char* command = binding->command; list_t *args = split_string(command, " "); if (strcmp("workspace", args->items[0]) == 0 && args->length > 1) { sway_log(L_DEBUG, "Got valid workspace command for target: '%s'", (char *)args->items[1]); char* target = malloc(strlen(args->items[1]) + 1); strcpy(target, args->items[1]); while (*target == ' ' || *target == '\t') target++; // Make sure that the command references an actual workspace // not a command about workspaces if (strcmp(target, "next") == 0 || strcmp(target, "prev") == 0 || strcmp(target, "next_on_output") == 0 || strcmp(target, "prev_on_output") == 0 || strcmp(target, "number") == 0 || strcmp(target, "back_and_forth") == 0 || strcmp(target, "current") == 0) { free_flat_list(args); continue; } // Make sure that the workspace doesn't already exist if (workspace_by_name(target)) { free_flat_list(args); continue; } free_flat_list(args); sway_log(L_DEBUG, "Workspace: Found free name %s", target); return target; } free_flat_list(args); } // As a fall back, get the current number of active workspaces // and return that + 1 for the next workspace's name int ws_num = root_container.children->length; if (ws_num >= 10) { l = 2; } else if (ws_num >= 100) { l = 3; } char *name = malloc(l + 1); sprintf(name, "%d", ws_num++); return name; }
void ipc_client_handle_command(struct ipc_client *client) { if (!sway_assert(client != NULL, "client != NULL")) { return; } char buf[client->payload_length + 1]; if (client->payload_length > 0) { ssize_t received = recv(client->fd, buf, client->payload_length, 0); if (received == -1) { sway_log_errno(L_INFO, "Unable to receive payload from IPC client"); ipc_client_disconnect(client); return; } } switch (client->current_command) { case IPC_COMMAND: { buf[client->payload_length] = '\0'; bool success = handle_command(config, buf); char reply[64]; int length = snprintf(reply, sizeof(reply), "{\"success\":%s}", success ? "true" : "false"); ipc_send_reply(client, reply, (uint32_t) length); break; } case IPC_GET_WORKSPACES: { list_t *workspaces = create_list(); container_map(&root_container, ipc_get_workspaces_callback, workspaces); char *json = json_list(workspaces); free_flat_list(workspaces); ipc_send_reply(client, json, strlen(json)); free(json); break; } case IPC_GET_OUTPUTS: { list_t *outputs = create_list(); container_map(&root_container, ipc_get_outputs_callback, outputs); char *json = json_list(outputs); free_flat_list(outputs); ipc_send_reply(client, json, strlen(json)); free(json); break; } default: sway_log(L_INFO, "Unknown IPC command type %i", client->current_command); ipc_client_disconnect(client); break; } client->payload_length = 0; }
static void free_config(struct sway_config *config) { int i; for (i = 0; i < config->symbols->length; ++i) { free_variable(config->symbols->items[i]); } list_free(config->symbols); for (i = 0; i < config->modes->length; ++i) { free_mode(config->modes->items[i]); } list_free(config->modes); free_flat_list(config->cmd_queue); for (i = 0; i < config->workspace_outputs->length; ++i) { free_workspace_output(config->workspace_outputs->items[i]); } list_free(config->workspace_outputs); for (i = 0; i < config->criteria->length; ++i) { free_criteria(config->criteria->items[i]); } list_free(config->criteria); for (i = 0; i < config->output_configs->length; ++i) { free_output_config(config->output_configs->items[i]); } list_free(config->output_configs); free(config); }
static void free_binding(struct sway_binding *bind) { if (!bind) { return; } free_flat_list(bind->keys); free(bind->command); free(bind); }
static void handle_wlc_ready(void) { sway_log(L_DEBUG, "Compositor is ready, executing cmds in queue"); int i; for (i = 0; i < config->cmd_queue->length; ++i) { handle_command(config, config->cmd_queue->items[i]); } free_flat_list(config->cmd_queue); config->active = true; }
void free_config(struct sway_config *config) { int i; for (i = 0; i < config->modes->length; ++i) { free_mode((struct sway_mode *)config->modes->items[i]); } free_flat_list(config->modes); for (i = 0; i < config->workspace_outputs->length; ++i) { struct workspace_output *wso = config->workspace_outputs->items[i]; free(wso->output); free(wso->workspace); } free_flat_list(config->workspace_outputs); free_flat_list(config->cmd_queue); for (i = 0; i < config->symbols->length; ++i) { struct sway_variable *sym = config->symbols->items[i]; free(sym->name); free(sym->value); } free_flat_list(config->symbols); }
static void free_bar(struct bar_config *bar) { if (!bar) { return; } free(bar->mode); free(bar->hidden_state); free(bar->status_command); free(bar->font); free(bar->separator_symbol); int i; for (i = 0; bar->bindings && i < bar->bindings->length; ++i) { free_sway_mouse_binding(bar->bindings->items[i]); } list_free(bar->bindings); if (bar->outputs) { free_flat_list(bar->outputs); } if (bar->pid != 0) { terminate_swaybar(bar->pid); } free(bar->colors.background); free(bar->colors.statusline); free(bar->colors.separator); free(bar->colors.focused_background); free(bar->colors.focused_statusline); free(bar->colors.focused_separator); free(bar->colors.focused_workspace_border); free(bar->colors.focused_workspace_bg); free(bar->colors.focused_workspace_text); free(bar->colors.active_workspace_border); free(bar->colors.active_workspace_bg); free(bar->colors.active_workspace_text); free(bar->colors.inactive_workspace_border); free(bar->colors.inactive_workspace_bg); free(bar->colors.inactive_workspace_text); free(bar->colors.urgent_workspace_border); free(bar->colors.urgent_workspace_bg); free(bar->colors.urgent_workspace_text); free(bar->colors.binding_mode_border); free(bar->colors.binding_mode_bg); free(bar->colors.binding_mode_text); free(bar); }
int create_virtual_subscriptions(rl_subscription_t *ss, int nesting_level) { flat_list_t *flat = NULL; int res = 0; str_t *ss_uri = NULL; str_t *ss_package = NULL; ss_uri = rls_get_uri(ss); ss_package = rls_get_package(ss); res = xcap_query_rls_services(&ss->xcap_params, ss_uri, ss_package, &flat); if (res != RES_OK) return res; /* go through flat list and find/create virtual subscriptions */ res = add_virtual_subscriptions(ss, flat, nesting_level); DEBUG_LOG("rli_create_content(): freeing flat list\n"); free_flat_list(flat); return RES_OK; }
void registry_teardown(struct registry *registry) { if (registry->pointer) { wl_pointer_destroy(registry->pointer); } if (registry->seat) { wl_seat_destroy(registry->seat); } if (registry->shell) { wl_shell_destroy(registry->shell); } if (registry->shm) { wl_shm_destroy(registry->shm); } if (registry->compositor) { wl_compositor_destroy(registry->compositor); } if (registry->display) { wl_display_disconnect(registry->display); } if (registry->outputs) { free_flat_list(registry->outputs); } free(registry); }
static char *get_config_path(void) { char *config_path = NULL; char *paths[3] = { getenv("HOME"), getenv("XDG_CONFIG_HOME"), "" }; int pathlen[3] = { 0, 0, 0 }; int i; #define home paths[0] #define conf paths[1] // Get home and config directories conf = conf ? strdup(conf) : NULL; home = home ? strdup(home) : NULL; // If config folder is unset, set it to $HOME/.config if (!conf && home) { const char *def = "/.config"; conf = malloc(strlen(home) + strlen(def) + 1); strcpy(conf, home); strcat(conf, def); } // Get path lengths pathlen[0] = home ? strlen(home) : 0; pathlen[1] = conf ? strlen(conf) : 0; #undef home #undef conf // Search for config file from search paths static const char *search_paths[] = { "/.sway/config", // Prepend with $home "/sway/config", // Prepend with $config "/etc/sway/config", "/.i3/config", // $home "/i3/config", // $config "/etc/i3/config" }; for (i = 0; i < (int)(sizeof(search_paths) / sizeof(char *)); ++i) { // Only try path if it is set by enviroment variables if (paths[i%3]) { char *test = malloc(pathlen[i%3] + strlen(search_paths[i]) + 1); strcpy(test, paths[i%3]); strcpy(test + pathlen[i%3], search_paths[i]); sway_log(L_DEBUG, "Checking for config at %s", test); if (file_exists(test)) { config_path = test; goto cleanup; } free(test); } } sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS"); char *xdg_config_dirs = getenv("XDG_CONFIG_DIRS"); if (xdg_config_dirs) { list_t *paths = split_string(xdg_config_dirs, ":"); const char *name = "/sway/config"; for (i = 0; i < paths->length; i++ ) { char *test = malloc(strlen(paths->items[i]) + strlen(name) + 1); strcpy(test, paths->items[i]); strcat(test, name); if (file_exists(test)) { config_path = test; break; } free(test); } free_flat_list(paths); } cleanup: free(paths[0]); free(paths[1]); return config_path; }
bool load_main_config(const char *file, bool is_active) { input_init(); char *path; if (file != NULL) { path = strdup(file); } else { path = get_config_path(); } struct sway_config *old_config = config; config = calloc(1, sizeof(struct sway_config)); if (!config) { sway_abort("Unable to allocate config"); } config_defaults(config); if (is_active) { sway_log(L_DEBUG, "Performing configuration file reload"); config->reloading = true; config->active = true; } config->current_config = path; list_add(config->config_chain, path); config->reading = true; // Read security configs bool success = true; DIR *dir = opendir(SYSCONFDIR "/sway/security.d"); if (!dir) { sway_log(L_ERROR, "%s does not exist, sway will have no security configuration" " and will probably be broken", SYSCONFDIR "/sway/security.d"); } else { list_t *secconfigs = create_list(); char *base = SYSCONFDIR "/sway/security.d/"; struct dirent *ent = readdir(dir); struct stat s; while (ent != NULL) { char *_path = malloc(strlen(ent->d_name) + strlen(base) + 1); strcpy(_path, base); strcat(_path, ent->d_name); lstat(_path, &s); if (S_ISREG(s.st_mode)) { list_add(secconfigs, _path); } ent = readdir(dir); } closedir(dir); list_qsort(secconfigs, qstrcmp); for (int i = 0; i < secconfigs->length; ++i) { char *_path = secconfigs->items[i]; if (stat(_path, &s) || s.st_uid != 0 || s.st_gid != 0 || (((s.st_mode & 0777) != 0644) && (s.st_mode & 0777) != 0444)) { sway_log(L_ERROR, "Refusing to load %s - it must be owned by root and mode 644 or 444", _path); success = false; } else { success = success && load_config(_path, config); } } free_flat_list(secconfigs); } success = success && load_config(path, config); if (is_active) { config->reloading = false; } if (old_config) { free_config(old_config); } config->reading = false; if (success) { update_active_bar_modifiers(); } return success; }
int main(int argc, char **argv) { init_scas_runtime(); parse_arguments(argc, argv); init_log(scas_runtime.verbosity); validate_scas_runtime(); instruction_set_t *instruction_set = find_inst(); scas_log(L_INFO, "Loaded instruction set: %s", instruction_set->arch); list_t *include_path = split_include_path(); list_t *errors = create_list(); list_t *warnings = create_list(); list_t *objects = create_list(); int i; for (i = 0; i < scas_runtime.input_files->length; ++i) { scas_log(L_INFO, "Assembling input file: '%s'", scas_runtime.input_files->items[i]); indent_log(); FILE *f; if (strcasecmp(scas_runtime.input_files->items[i], "-") == 0) { f = stdin; } else { f = fopen(scas_runtime.input_files->items[i], "r"); } if (!f) { scas_abort("Unable to open '%s' for assembly.", scas_runtime.input_files->items[i]); } char magic[7]; bool is_object = false; if (fread(magic, sizeof(char), 7, f) == 7) { if (strncmp("SCASOBJ", magic, 7) == 0) { is_object = true; } } fseek(f, 0L, SEEK_SET); object_t *o; if (is_object) { scas_log(L_INFO, "Loading object file '%s'", scas_runtime.input_files->items[i]); o = freadobj(f, scas_runtime.input_files->items[i]); } else { assembler_settings_t settings = { .include_path = include_path, .set = instruction_set, .errors = errors, .warnings = warnings, .macros = scas_runtime.macros, }; o = assemble(f, scas_runtime.input_files->items[i], &settings); fclose(f); scas_log(L_INFO, "Assembler returned %d errors, %d warnings for '%s'", errors->length, warnings->length, scas_runtime.input_files->items[i]); } list_add(objects, o); deindent_log(); } scas_log(L_DEBUG, "Opening output file for writing: %s", scas_runtime.output_file); FILE *out; if (strcasecmp(scas_runtime.output_file, "-") == 0) { out = stdout; } else { out = fopen(scas_runtime.output_file, "w+"); } if (!out) { scas_abort("Unable to open '%s' for output.", scas_runtime.output_file); } if ((scas_runtime.jobs & LINK) == LINK) { scas_log(L_INFO, "Passing objects to linker"); linker_settings_t settings = { .automatic_relocation = scas_runtime.options.auto_relocation, .merge_only = (scas_runtime.jobs & MERGE) == MERGE, .errors = errors, .warnings = warnings, .write_output = scas_runtime.options.output_format }; if (settings.merge_only) { object_t *merged = merge_objects(objects); fwriteobj(out, merged); } else { link_objects(out, objects, &settings); } scas_log(L_INFO, "Linker returned %d errors, %d warnings", errors->length, warnings->length); } else { scas_log(L_INFO, "Skipping linking - writing to object file"); object_t *merged = merge_objects(objects); fwriteobj(out, merged); fflush(out); fclose(out); } if (errors->length != 0) { int i; for (i = 0; i < errors->length; ++i) { error_t *error = errors->items[i]; fprintf(stderr, "%s:%d:%d: error #%d: %s\n", error->file_name, (int)error->line_number, (int)error->column, error->code, error->message); fprintf(stderr, "%s\n", error->line); if (error->column != 0) { int j; for (j = error->column; j > 0; --j) { fprintf(stderr, "."); } fprintf(stderr, "^\n"); } else { fprintf(stderr, "\n"); } } remove(scas_runtime.output_file); } if (warnings->length != 0) { int i; for (i = 0; i < errors->length; ++i) { warning_t *warning = warnings->items[i]; fprintf(stderr, "%s:%d:%d: warning #%d: %s\n", warning->file_name, (int)warning->line_number, (int)warning->column, warning->code, get_warning_string(warning)); fprintf(stderr, "%s\n", warning->line); if (warning->column != 0) { int j; for (j = warning->column; j > 0; --j) { fprintf(stderr, "."); } fprintf(stderr, "^\n"); } } } int ret = errors->length; scas_log(L_DEBUG, "Exiting with status code %d, cleaning up", ret); list_free(scas_runtime.input_files); free_flat_list(include_path); list_free(objects); list_free(errors); list_free(warnings); instruction_set_free(instruction_set); return ret; }
void free_config(struct sway_config *config) { if (!config) { return; } int i; for (i = 0; config->symbols && i < config->symbols->length; ++i) { free_variable(config->symbols->items[i]); } list_free(config->symbols); for (i = 0; config->modes && i < config->modes->length; ++i) { free_mode(config->modes->items[i]); } list_free(config->modes); for (i = 0; config->bars && i < config->bars->length; ++i) { free_bar(config->bars->items[i]); } list_free(config->bars); free_flat_list(config->cmd_queue); for (i = 0; config->workspace_outputs && i < config->workspace_outputs->length; ++i) { free_workspace_output(config->workspace_outputs->items[i]); } list_free(config->workspace_outputs); for (i = 0; config->pid_workspaces && i < config->pid_workspaces->length; ++i) { free_pid_workspace(config->pid_workspaces->items[i]); } list_free(config->pid_workspaces); for (i = 0; config->criteria && i < config->criteria->length; ++i) { free_criteria(config->criteria->items[i]); } list_free(config->criteria); for (i = 0; config->input_configs && i < config->input_configs->length; ++i) { free_input_config(config->input_configs->items[i]); } list_free(config->input_configs); for (i = 0; config->output_configs && i < config->output_configs->length; ++i) { free_output_config(config->output_configs->items[i]); } list_free(config->output_configs); for (i = 0; config->command_policies && i < config->command_policies->length; ++i) { free_command_policy(config->command_policies->items[i]); } list_free(config->command_policies); for (i = 0; config->feature_policies && i < config->feature_policies->length; ++i) { free_feature_policy(config->feature_policies->items[i]); } list_free(config->feature_policies); list_free(config->active_bar_modifiers); free_flat_list(config->config_chain); free(config->font); free(config->floating_scroll_up_cmd); free(config->floating_scroll_down_cmd); free(config->floating_scroll_left_cmd); free(config->floating_scroll_right_cmd); free(config); }
int get_rls(const str_t *uri, xcap_query_params_t *xcap_params, const str_t *package, flat_list_t **dst) { char *data = NULL; int dsize = 0; service_t *service = NULL; char *xcap_uri = NULL; str_t *filename = NULL; int res; if (!dst) return RES_INTERNAL_ERR; /* get basic document */ xcap_uri = xcap_uri_for_global_document(xcap_doc_rls_services, filename, xcap_params); if (!xcap_uri) { ERROR_LOG("can't get XCAP uri\n"); return RES_XCAP_QUERY_ERR; } res = xcap_query(xcap_uri, xcap_params, &data, &dsize); if (res != 0) { ERROR_LOG("XCAP problems for uri \'%s\'\n", xcap_uri); if (data) { cds_free(data); } cds_free(xcap_uri); return RES_XCAP_QUERY_ERR; } cds_free(xcap_uri); /* parse document as a service element in rls-sources */ if (parse_service(data, dsize, &service) != 0) { ERROR_LOG("Parsing problems!\n"); if (service) free_service(service); if (data) { cds_free(data); } return RES_XCAP_PARSE_ERR; } /* DEBUG_LOG("%.*s\n", dsize, data);*/ if (data) cds_free(data); if (!service) { DEBUG_LOG("Empty service!\n"); return RES_XCAP_QUERY_ERR; } /* verify the package */ if (verify_package(service, package) != 0) { free_service(service); return RES_BAD_EVENT_PACKAGE_ERR; } /* create flat document */ res = create_flat_list(service, xcap_params, dst); if (res != RES_OK) { ERROR_LOG("Flat list creation error\n"); free_service(service); free_flat_list(*dst); *dst = NULL; return res; } free_service(service); return RES_OK; }
static void free_binding(struct sway_binding *bind) { free_flat_list(bind->keys); free(bind->command); free(bind); }
int get_rls_from_full_doc(const str_t *uri, /* const str_t *filename, */ xcap_query_params_t *xcap_params, const str_t *package, flat_list_t **dst) { char *data = NULL; int dsize = 0; rls_services_t *rls = NULL; service_t *service = NULL; str_t curi; int res; char *xcap_uri = NULL; str_t *filename = NULL; if (!dst) return RES_INTERNAL_ERR; /* get basic document */ xcap_uri = xcap_uri_for_global_document(xcap_doc_rls_services, filename, xcap_params); if (!xcap_uri) { ERROR_LOG("can't get XCAP uri\n"); return -1; } res = xcap_query(xcap_uri, xcap_params, &data, &dsize); if (res != 0) { ERROR_LOG("XCAP problems for uri \'%s\'\n", xcap_uri); if (data) { cds_free(data); } cds_free(xcap_uri); return RES_XCAP_QUERY_ERR; } cds_free(xcap_uri); /* parse document as a service element in rls-sources */ if (parse_rls_services_xml(data, dsize, &rls) != 0) { ERROR_LOG("Parsing problems!\n"); if (rls) free_rls_services(rls); if (data) { cds_free(data); } return RES_XCAP_PARSE_ERR; } /* DEBUG_LOG("%.*s\n", dsize, data);*/ if (data) cds_free(data); /* try to find given service according to uri */ canonicalize_uri(uri, &curi); service = find_service(rls, &curi); if (!service) DEBUG_LOG("Service %.*s not found!\n", FMT_STR(curi)); str_free_content(&curi); if (!service) { if (rls) free_rls_services(rls); return RES_XCAP_QUERY_ERR; } /* verify the package */ if (verify_package(service, package) != 0) { free_rls_services(rls); return RES_BAD_EVENT_PACKAGE_ERR; } /* create flat document */ res = create_flat_list(service, xcap_params, dst); if (res != RES_OK) { ERROR_LOG("Flat list creation error\n"); free_rls_services(rls); free_flat_list(*dst); *dst = NULL; return res; } free_rls_services(rls); return RES_OK; }
static char *get_config_path() { char *home = getenv("HOME"); if (home) { home = strdup(getenv("HOME")); } char *config = getenv("XDG_CONFIG_HOME"); if (config) { config = strdup(getenv("XDG_CONFIG_HOME")); } else if (home) { const char *def = "/.config"; config = malloc(strlen(home) + strlen(def) + 1); strcpy(config, home); strcat(config, def); } else { home = strdup(""); config = strdup(""); } // Set up a temporary config for holding set variables struct sway_config *temp_config = malloc(sizeof(struct sway_config)); config_defaults(temp_config); const char *set_home = "set $home "; char *_home = malloc(strlen(home) + strlen(set_home) + 1); strcpy(_home, set_home); strcat(_home, home); handle_command(temp_config, _home); free(_home); const char *set_config = "set $config "; char *_config = malloc(strlen(config) + strlen(set_config) + 1); strcpy(_config, set_config); strcat(_config, config); handle_command(temp_config, _config); free(_config); char *test = NULL; int i; for (i = 0; i < (int)(sizeof(search_paths) / sizeof(char *)); ++i) { test = strdup(search_paths[i]); test = do_var_replacement(temp_config, test); sway_log(L_DEBUG, "Checking for config at %s", test); if (exists(test)) { goto _continue; } free(test); test = NULL; } sway_log(L_DEBUG, "Trying to find config in XDG_CONFIG_DIRS"); char *xdg_config_dirs = getenv("XDG_CONFIG_DIRS"); if (xdg_config_dirs != NULL) { list_t *paths = split_string(xdg_config_dirs, ":"); char *name = "/sway/config"; int i; for (i = 0; i < paths->length; i++ ) { test = malloc(strlen(paths->items[i]) + strlen(name) + 1); strcpy(test, paths->items[i]); strcat(test, name); if (exists(test)) { free_flat_list(paths); return test; } free(test); test = NULL; } free_flat_list(paths); } _continue: free_config(temp_config); free(home); free(config); return test; }
/* catches and processes user's resource list as rls-services document */ int get_resource_list_from_full_doc(const str_t *user, const str_t *filename, xcap_query_params_t *xcap_params, const char *list_name, flat_list_t **dst) { char *data = NULL; int dsize = 0; service_t *service = NULL; list_t *list = NULL, *right = NULL; int res; char *uri = NULL; if (!dst) return RES_INTERNAL_ERR; /* get basic document */ uri = xcap_uri_for_users_document(xcap_doc_resource_lists, user, filename, xcap_params); if (!uri) { ERROR_LOG("can't get XCAP uri\n"); return -1; } DEBUG_LOG("XCAP uri \'%s\'\n", uri); res = xcap_query(uri, xcap_params, &data, &dsize); if (res != 0) { ERROR_LOG("XCAP problems for uri \'%s\'\n", uri); if (data) { cds_free(data); } cds_free(uri); return RES_XCAP_QUERY_ERR; } cds_free(uri); /* parse document as a list element in resource-lists */ if (parse_as_list_content_xml(data, dsize, &list) != 0) { ERROR_LOG("Parsing problems!\n"); if (list) free_list(list); if (data) { cds_free(data); } return RES_XCAP_PARSE_ERR; } /* DEBUG_LOG("%.*s\n", dsize, data);*/ if (data) cds_free(data); /* rs -> list */ if (!list) { ERROR_LOG("Empty resource list!\n"); *dst = NULL; return 0; /* this is not error! */ /* return RES_INTERNAL_ERR; */ } /* search for right list element */ right = find_list(list, list_name); service = (service_t*)cds_malloc(sizeof(*service)); if (!service) { ERROR_LOG("Can't allocate memory!\n"); return RES_MEMORY_ERR; } memset(service, 0, sizeof(*service)); service->content_type = stc_list; service->content.list = right; /*service->uri = ??? */ /* create flat document */ res = create_flat_list(service, xcap_params, dst); service->content.list = list; /* free whole document not only "right" list */ free_service(service); if (res != RES_OK) { ERROR_LOG("Flat list creation error\n"); free_flat_list(*dst); *dst = NULL; return res; } return RES_OK; }
void free_mode(struct sway_mode *mode) { free(mode->name); free_flat_list(mode->bindings); }