diff options
-rw-r--r-- | extensions/perdomainsettings | 2 | ||||
-rw-r--r-- | tools/Makefile | 11 | ||||
-rw-r--r-- | tools/dwbem.c | 722 |
3 files changed, 731 insertions, 4 deletions
diff --git a/extensions/perdomainsettings b/extensions/perdomainsettings index 6b0c43b5..c72958ca 100644 --- a/extensions/perdomainsettings +++ b/extensions/perdomainsettings @@ -118,7 +118,7 @@ var defaultConfig = { // Default settings, for each setting in domains, hosts and uris a // default-value should be specified, e.g. - // uris : { autoLoadImages : false }, + // defaults : { autoLoadImages : false }, defaults : {} //>DEFAULT_CONFIG diff --git a/tools/Makefile b/tools/Makefile index a8b62b81..7552350e 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,14 +1,19 @@ -include ../config.mk +TARGET=dwbem -TARGET=dwb_em +CFLAGS += -g -std=c99 -Wall +LDFLAGS += -lreadline all: $(TARGET) -$(TARGET): dwb_em.in +dwb_em: dwb_em.in @echo gen $@ $(shell sed 's#@SYSTEM_DIR@#$(DATADIR)/$(REAL_NAME)/$(EXTENSIONDIR)#' $< > $@) @chmod 755 $@ +$(TARGET): dwbem.c + @echo $(CC) $< -o $@ + @$(CC) $(CFLAGS) $(LDFLAGS) $(shell pkg-config --cflags --libs libsoup-2.4) $< -o $@ + clean: rm -f $(TARGET) diff --git a/tools/dwbem.c b/tools/dwbem.c new file mode 100644 index 00000000..d78e833a --- /dev/null +++ b/tools/dwbem.c @@ -0,0 +1,722 @@ +#define _BSD_SOURCE +#define _POSIX_SOURCE + +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> +#include <termios.h> +#include <ctype.h> +#include <stdlib.h> +#include <fcntl.h> +#include <stdarg.h> +#include <readline/readline.h> +#include <sys/stat.h> +#include <glib-2.0/glib.h> +#include <libsoup-2.4/libsoup/soup.h> +#define API_BASE "https://api.bitbucket.org/1.0/repositories/portix/dwb_extensions/src/tip/src/?format=yaml" +#define REPO_BASE "https://bitbucket.org/portix/dwb_extensions/raw/tip/src" +#define SKIP(line, c) do{ \ + while(*line && *line != c)line++; line++; } while(0) +#define EXTENSION_DIR() (g_build_filename(g_get_user_data_dir(), "dwb", "extensions", NULL)) +#ifndef false +#define false 0 +#endif +#ifndef true +#define true (!false) +#endif +#define TMPL_CONFIG "___CONFIG" +#define TMPL_SCRIPT "___SCRIPT" +#define TMPL_DISABLED "___DISABLED" +#define REGEX_REPLACE(X, name) (g_strdup_printf("(?<=^|\n)//<%s"TMPL_##X".*//>%s"TMPL_##X"\\s*(?=\n|$|/*)\\s*", name, name)) +#define REGEX(X, name) (g_strdup_printf("(?<=^|\n)//<%s"TMPL_##X"|//>%s"TMPL_##X"\\s*(?=\n|$|/*)\\s*", name, name)) +#define EXT(name) "\033[1m"#name"\033[0m" +#define FREE0(X) (X == NULL ? NULL : (X = (g_free(X), NULL))) +enum { + F_NO_CONFIG = 1<<0, + F_BIND = 1<<1, + F_FORCE = 1<<2, + F_UPDATE = 1<<2 +}; + +static char *m_meta_data; +static char *m_installed; +static char *m_user_dir; +static char *m_system_dir; +static char *m_loader; +static const char *m_editor; +static const char *m_diff; +static SoupSession *session; + +void +vprint_error(const char *format, va_list args) { + fputs("\033[31m!!!\033[0m ", stderr); + vfprintf(stderr, format, args); + fputc('\n', stderr); +} +void +print_error(const char *format, ...) { + va_list args; + va_start(args, format); + vprint_error(format, args); + va_end(args); +} +void +notify(const char *format, ...) { + va_list args; + va_start(args, format); + fputs("\033[32m==>\033[0m ", stderr); + vfprintf(stderr, format, args); + fputc('\n', stderr); + va_end(args); +} + +void +die(int status, const char *format, ...) { + va_list args; + va_start(args, format); + vprint_error(format, args); + va_end(args); + exit(status); +} +void +check_dir(const char *dir) { + if (!g_file_test(dir, G_FILE_TEST_IS_DIR)) + g_mkdir_with_parents(dir, 0700); +} + +static int +regex_replace_file(const char *path, const char *regex, const char *replacement) { + int ret = -1; + char *content = NULL; + if (g_file_get_contents(path, &content, NULL, NULL)) { + char **matches = g_regex_split_simple(regex, content, G_REGEX_DOTALL, 0); + if (matches[0]) { + g_free(content); + content = g_strdup_printf("%s%s%s", matches[0], replacement ? replacement : "", matches[1] ? matches[1] : ""); + if (g_file_set_contents(path, content, -1, NULL)) + ret = 0; + } + g_strfreev(matches); + } + g_free(content); + return ret; +} +static char * +get_data(const char *name, const char *template, gboolean multiline) { + char *format; + if (multiline) + format = "(?<=^|\n)/\\*<%s%s|%s%s>\\*/\\s*(?=\n|$|/*)\\s*"; + else + format = "(?<=^|\n)//<%s%s|//>%s%s\\s*(?=\n|$|/*)\\s*"; + char *regex = g_strdup_printf(format, name, template, name, template); + char *ret = NULL; + char *content = NULL; + if (g_file_get_contents(m_loader, &content, NULL, NULL)) { + char **matches = g_regex_split_simple(regex, content, G_REGEX_DOTALL, 0); + if (matches[1] != NULL) + ret = g_strdup(matches[1]); + g_strfreev(matches); + } + g_free(content); + g_free(regex); + return ret; +} + + +size_t +grep(const char *filename, const char *beg, char *buffer, size_t length) { + FILE *f = fopen(filename, "r"); + char line[128]; + int i = -1; + if (f == NULL) + return -1; + while(fgets(line, 128, f) != NULL) { + if (g_str_has_prefix(line, beg)) { + i=0; + while (line[i] && line[i] != '\n' && i<length-1) { + buffer[i] = line[i]; + i++; + } + buffer[i++] = '\0'; + break; + } + } + fclose(f); + return i; +} +static int +update_installed(const char *name, const char *meta) { + char buffer[128]; + snprintf(buffer, 128, "%s\n", meta); + char *regex = g_strdup_printf("(?<=^|\n)%s\\s\\w+\n", name); + regex_replace_file(m_installed, regex, buffer); + g_free(regex); + + return 0; + +} +static int +yes_no(int preset, const char *format, ...) { + va_list args; + char *response; + va_start(args, format); + int ret = -1; + char buffer[512]; + char cformat[512]; + snprintf(cformat, 512, "\033[34m:::\033[0m %s %s? ", format, preset ? "(Y/n)" : "(y/N)"); + va_start(args, format); + vsnprintf(buffer, 512, cformat, args); + va_end(args); + while (ret == -1) { + response = readline(buffer); + if (response != NULL) { + char *backup = response; + g_strstrip(response); + if (*response == '\0') + ret = preset; + else if (! strcasecmp("y", response)) + ret = 1; + else if (! strcasecmp("n", response)) + ret = 0; + else + print_error("try again"); + g_free(backup); + } + else + ret = preset; + } + va_end(args); + return ret; +} +char * +get_response(const char *format, ...) { + char buffer[512]; + char cformat[512]; + va_list args; + snprintf(cformat, 512, "\033[34m:::\033[0m %s ", format); + va_start(args, format); + vsnprintf(buffer, 512, cformat, args); + va_end(args); + return readline(buffer); +} +int +diff(const char *text1, const char *text2, char **ret) { + if (g_strcmp0(text1, text2) == 0 || text1 == NULL || text2 == NULL) { + *ret = NULL; + return 0; + } + gboolean spawn_success = true; + GError *e = NULL; + char *new_text = NULL; + char file1[32], file2[32]; + strcpy(file1, "/tmp/tmpXXXXXXorig.js"); + strcpy(file2, "/tmp/tmpXXXXXXnew.js"); + char *text2_new = g_strdup_printf("// THIS WILL BE DISCARDED\n%s", text2); + if (g_file_set_contents(file1, text1, -1, &e) && g_file_set_contents(file2, text2_new, -1, &e)) { + char *args[4]; + args[0] = (char *)m_diff; + args[1] = file1; + args[2] = file2; + args[3] = NULL; + spawn_success = g_spawn_sync(NULL, args, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_CHILD_INHERITS_STDIN, NULL, NULL, NULL, NULL, NULL, NULL); + if (spawn_success) + g_file_get_contents(file1, &new_text, NULL, NULL); + unlink(file1); + unlink(file2); + } + else { + print_error("Cannot diff : %s", e->message); + } + g_free(text2_new); + if (!spawn_success) + die(1, "Cannot spawn "EXT(%s)", please set "EXT(EDITOR)" to an appropriate value", m_editor); + *ret = new_text; + return 1; +} +char * +edit(const char *text) { + char *new_config = NULL; + char buffer[32]; + strcpy(buffer, "/tmp/tmpXXXXXX.js"); + mkstemps(buffer, 3); + gboolean spawn_success = true; + if (g_file_set_contents(buffer, text, -1, NULL)) { + char *args[3]; + args[0] = (char*)m_editor; + args[1] = buffer; + args[2] = NULL; + + spawn_success = g_spawn_sync(NULL, args, NULL, G_SPAWN_SEARCH_PATH | G_SPAWN_CHILD_INHERITS_STDIN, NULL, NULL, NULL, NULL, NULL, NULL); + if (spawn_success) + g_file_get_contents(buffer, &new_config, NULL, NULL); + unlink(buffer); + } + if (!spawn_success) + die(1, "Cannot spawn "EXT(%s)", please set "EXT(EDITOR)" to an appropriate value", m_editor); + return new_config; +} +static void +set_loader(const char *name, const char *config, int flags) { + char *script = NULL; + char *shortcut = NULL, *command = NULL; + gboolean load; + if (flags & F_BIND) { + while ((shortcut = get_response("Shortcut for toggling "EXT(%s)"?", name)) == NULL || *shortcut == '\0') + g_free(shortcut); + load = yes_no(1, "Load "EXT(%s)" on startup", name); + command = get_response("Command for toggling "EXT(%s)"?", name); + } + if (config == NULL || flags & F_NO_CONFIG) { + if (flags & F_BIND) + script = g_strdup_printf("//<%s"TMPL_SCRIPT"\nextensions.bind(\"%s\", \"%s\", {\n" + " load : %s%s%s%s\n});\n//>%s"TMPL_SCRIPT"\n", + name, name, shortcut, + load ? "true" : "false", + command != NULL && *command != '\0' ? ",\n command : \"" : "", + command != NULL && *command != '\0' ? command : "", + command != NULL && *command != '\0' ? "\"" : "", + name); + else { + script = g_strdup_printf("//<%s"TMPL_SCRIPT"\nextensions.load(\"%s\");\n//>%s"TMPL_SCRIPT"\n", name, name, name); + } + } + else { + if (flags & F_BIND) { + script = g_strdup_printf("//<%s"TMPL_SCRIPT"\n" + "var config_%s = {\n" + "//<%s"TMPL_CONFIG"%s//<%s"TMPL_CONFIG"\n};\n" + "extensions.bind(\"%s\", \"%s\", {\n" + " config : config_%s,\n" + " load : %s%s%s%s\n});\n//>%s"TMPL_SCRIPT"\n", + name, name, name, config, name, name, shortcut, name, + load ? "true" : "false", + command != NULL && *command != '\0' ? ",\n command : \"" : "", + command != NULL && *command != '\0' ? command : "", + command != NULL && *command != '\0' ? "\"" : "", + name); + } + else { + script = g_strdup_printf("//<%s"TMPL_SCRIPT"\nextensions.load(\"%s\", {\n" + "//<%s"TMPL_CONFIG"%s//>%s"TMPL_CONFIG"\n});\n//>%s"TMPL_SCRIPT"\n", + name, name, name, config, name, name); + } + } + if (! g_file_test(m_loader, G_FILE_TEST_EXISTS) ) { + char *file_content = g_strdup_printf("#!javascript\n%s", script); + g_file_set_contents(m_loader, file_content, -1, NULL); + g_free(file_content); + } + else { + char *regex = REGEX_REPLACE(SCRIPT, name); + regex_replace_file(m_loader, regex, script); + g_free(regex); + } + notify(EXT(%s)" added to loaderscript", name, m_loader); +} +static int +add_to_loader(const char *name, const char *content, int flags) { + g_return_val_if_fail(content != NULL, -1); + char *config = NULL; + const char *new_config = NULL; + gchar **matches = g_regex_split_simple("//<DEFAULT_CONFIG|//>DEFAULT_CONFIG", content, G_REGEX_DOTALL, 0); + + if (matches[1] == NULL) { + notify("No default configuration found"); + } + else if (flags & F_UPDATE) { + char *data = get_data(name, TMPL_CONFIG, false); + if (diff(data, matches[1], &config) == 0) { + notify("Config is up to date"); + } + else + new_config = config; + } + else if (!(flags & F_NO_CONFIG) && yes_no(1, "Edit configuration") == 1) { + new_config = config = edit(matches[1]); + } + else + new_config = matches[1]; + + set_loader(name, new_config, flags); + g_strfreev(matches); + g_free(config); + return 0; +} +static gboolean +check_installed(const char *name) { + char meta[128]; + if (grep(m_installed, name, meta, 128) == -1) + return false; + return true; +} +static int +install_extension(const char *name, int flags) { + int ret = -1; + char buffer[512]; + char meta[128]; + GError *e = NULL; + if (grep(m_meta_data, name, meta, 128) == -1) + die(1, "extension %s not found", name); + snprintf(buffer, 512, "%s/%s", m_system_dir, name); + if (g_file_test(buffer, G_FILE_TEST_EXISTS)) { + notify("Using %s", buffer); + char *content = NULL; + if (g_file_get_contents(buffer, &content, NULL, NULL) ) { + if (add_to_loader(name, content, flags) == 0) { + update_installed(name, meta); + ret = 0; + } + g_free(content); + } + else { + print_error("Opening %s failed", buffer); + } + } + else { + notify("Downloading "EXT(%s), name); + snprintf(buffer, 512, "%s/%s", REPO_BASE, name); + SoupMessage *msg = soup_message_new("GET", buffer); + int status = soup_session_send_message(session, msg); + if (status == 200 && msg->response_body->data) { + snprintf(buffer, 512, "%s/%s", m_user_dir, name); + if (g_file_set_contents(buffer, msg->response_body->data, -1, &e)) { + if (add_to_loader(name, msg->response_body->data, flags) == 0) { + update_installed(name, meta); + ret = 0; + } + } + else + print_error("Saving %s failed: %s", name, e->message); + } + else { + print_error("Download failed with status %d", status); + } + g_object_unref(msg); + } + return ret; +} + +int +sync_meta(const char *output) { + int ret = 0; + check_dir(m_user_dir); + + static gboolean sync = false; + if (sync) + return ret; + sync = true; + + notify("Syncing metadata"); + SoupMessage *msg = soup_message_new("GET", API_BASE); + int status = soup_session_send_message(session, msg); + + if (status == 200) { + if (msg->response_body && msg->response_body->data) { + FILE *file = fopen(output, "w"); + if (file == NULL) { + ret = -1; + print_error("Cannot open %s for writing", m_meta_data); + goto unwind; + } + const char *response = msg->response_body->data; + while(*response) { + while(isspace((int)*response)) + response++; + while (*response && *response != '-') { + SKIP(response, '\n'); + } + if (*response == '\n') + continue; + if (*response == '\0') + break; + SKIP(response, '/'); + while (*response && *response != ',') { + fputc(*(response++), file); + } + fputc(' ', file); + SKIP(response, ':'); + response += 2; + while (*response && *response != ',') { + fputc(*(response++), file); + } + fputc('\n', file); + SKIP(response, '\n'); + } + + GDir *d = g_dir_open(m_system_dir, 0, NULL); + if (d == NULL) + die(1, "Cannot open %s", m_system_dir); + const char *name; + struct stat st; + char buffer[1024]; + while((name = g_dir_read_name(d)) != NULL) { + snprintf(buffer, 1024, "%s/%s", m_system_dir, name); + if (stat(buffer, &st) != -1) { + fprintf(file, "%s %lu\n", name, st.st_mtime); + } + } + g_dir_close(d); + fclose(file); + } + } + else { + ret = -1; + print_error("Syncing failed, request returned with status %s\n", status); + } +unwind: + g_object_unref(msg); + return ret; + +} + +static int +set_data(const char *name, const char *template, const char *data, gboolean multiline) { + char *format; + if (multiline) + format = "(?<=^|\n)/\\*<%s%s.*%s%s>\\*/\\s*(?=\n|$)"; + else + format = "(?<=^|\n)//<%s%s.*//>%s%s\\s*(?=\n|$)"; + char *regex = g_strdup_printf(format, name, template, name, template); + char *content = NULL; + int ret = -1; + if (g_file_get_contents(m_loader, &content, NULL, NULL)) { + char **matches = g_regex_split_simple(regex, content, G_REGEX_DOTALL, 0); + GString *buffer = g_string_new(matches[0]); + if (multiline) { + g_string_append_printf(buffer, "/*<%s%s%s%s%s>*/\n", name, template, data ? data : "\n", name, template); + } + else { + g_string_append_printf(buffer, "//<%s%s%s//>%s%s\n", name, template, data ? data : "\n", name, template); + } + if (matches[1]) + g_string_append(buffer, matches[1]); + if (g_file_set_contents(m_loader, buffer->str, -1, NULL)) + ret = 0; + g_string_free(buffer, true); + } + g_free(regex); + g_free(content); + return ret; + +} +static void +change_config(const char *name, int flags) { + if (!check_installed(name)) + die(1, "Extension "EXT(%s)" is not installed", name); + char *config = get_data(name, TMPL_CONFIG, false); + char *new_config = NULL; + if (config) { + if (!(flags & F_NO_CONFIG)) { + new_config = edit(config); + g_free(config); + } + else + new_config = config; + set_loader(name, new_config, flags); + g_free(new_config); + } + else { + notify("No config found, you can use extensionrc instead"); + set_loader(name, NULL, flags); + } +} +static int +cl_install(const char *name, int flags) { + if (!(flags & F_FORCE) + && check_installed(name) + && !yes_no(0, EXT(%s)" is already installed, continue anyway", name)) + return -1; + notify("Installing "EXT(%s), name); + if (sync_meta(m_meta_data) == 0) { + return install_extension(name, flags); + } + return -1; +} +static void +cl_uninstall(const char *name) { + if (!check_installed(name)) + die(1, "extension %s is not installed", name); + char *path = g_build_filename(m_user_dir, name, NULL); + if (g_file_test(path, G_FILE_TEST_EXISTS)) { + notify("Removing %s", name); + unlink(path); + } + char *regex = REGEX_REPLACE(SCRIPT, name); + if (regex_replace_file(m_loader, regex, NULL) != -1) { + notify("Updating %s", m_loader); + } + g_free(regex); + regex = g_strdup_printf("(?<=^|\n)%s\\s\\w+\n", name); + if (regex_replace_file(m_installed, regex, NULL) != -1) { + notify("Updating metadata"); + } + g_free(regex); +} + +static void +cl_disable(const char *name) { + if (!check_installed(name)) + die(1, "Extension "EXT(%s)" is not installed", name); + char *regex = g_strdup_printf("(?<=^|\n)/\\*<%s"TMPL_DISABLED".*%s"TMPL_DISABLED">\\*/\\s*(?=$|\n)", name, name); + char *data = get_data(name, TMPL_SCRIPT, false); + if (!g_regex_match_simple(regex, data, G_REGEX_DOTALL, 0)) { + char *new_data = g_strdup_printf("\n/*<%s"TMPL_DISABLED"%s%s"TMPL_DISABLED">*/\n", name, data ? data : "\n", name); + if (set_data(name, TMPL_SCRIPT, new_data, false) != -1) + notify(EXT(%s)" disabled", name); + else + print_error("Unable to disable "EXT(%s), name); + g_free(new_data); + } + else + print_error(EXT(%s)" is already disabled", name); + g_free(data); + g_free(regex); +} +static void +cl_enable(const char *name) { + char *data = get_data(name, TMPL_DISABLED, true); + if (data != NULL) { + if (set_data(name, TMPL_SCRIPT, data, false) != -1) + notify(EXT(%s)" enabled", name); + else + print_error("Unable to enable "EXT(%s), name); + g_free(data); + } + else + print_error(EXT(%s)" is already enabled", name); +} +static void +do_upate(const char *meta, int flags) { + char buffer[128]; + char *space = strchr(meta, ' '); + if (space != NULL) { + snprintf(buffer, MIN(128, space - meta + 1), meta); + if (yes_no(1, "Update "EXT(%s), buffer)) + if (cl_install(buffer, flags | F_FORCE | F_UPDATE)) + notify(EXT(%s)" successfully updated", buffer); + } +} +static void +cl_update(int flags) { + sync_meta(m_meta_data); + char *meta = NULL; + char *installed = NULL; + size_t l_inst = 0, l_meta = 0; + if (!g_file_get_contents(m_installed, &installed, &l_inst, NULL) || l_inst == 0) + die(1, "No installed extensions found"); + if (!g_file_get_contents(m_meta_data, &meta, &l_meta, NULL) || l_meta == 0) + die(1, "Cannot open metadata"); + char **lines_inst = g_strsplit(installed, "\n", -1); + g_free(installed); + int updates = 0; + for (int i=0; lines_inst[i]; i++) { + if (*(lines_inst[i]) == '\0') + continue; + char *regex = g_strdup_printf("(?<=^|\n)%s(?=$|\n)", lines_inst[i]); + if (!g_regex_match_simple(regex, meta, G_REGEX_DOTALL, 0)) { + do_upate(lines_inst[i], flags); + updates++; + } + } + if (updates == 0) + notify("Up to date"); + else + notify("Done"); +} + +int +main(int argc, char **argv) { + g_type_init(); + gboolean missing = argc == 1; + char **o_install = NULL; + char **o_remove = NULL; + gboolean o_bind = false; + char **o_setbind = NULL; + char **o_setload = NULL; + char **o_disable = NULL; + char **o_enable = NULL; + gboolean o_noconfig = false; + gboolean o_update = false; + int flags = 0; + GOptionEntry options[] = { + { "install", 'i', 0, G_OPTION_ARG_STRING_ARRAY, &o_install, "Install extension", "extension" }, + { "remove", 'r', 0, G_OPTION_ARG_STRING_ARRAY, &o_remove, "Remove extension", "extension" }, + { "bind", 'b', 0, G_OPTION_ARG_NONE, &o_bind, "When installing an extension use extensions.bind instead of extensions.load", NULL }, + { "setbind", 'B', 0, G_OPTION_ARG_STRING_ARRAY, &o_setbind, "Edit configuration, use extensions.bind", "extension" }, + { "setload", 'L', 0, G_OPTION_ARG_STRING_ARRAY, &o_setload, "Edit configuration, use exensions.load", "extension" }, + { "noconfig", 'n', 0, G_OPTION_ARG_NONE, &o_noconfig, "Don't use config in loader script, use extensionrc instead", NULL }, + { "disable", 'd', 0, G_OPTION_ARG_STRING_ARRAY, &o_disable, "Disable extension", "extension" }, + { "enable", 'e', 0, G_OPTION_ARG_STRING_ARRAY, &o_enable, "Enable extension", "extension" }, + { "update", 'u', 0, G_OPTION_ARG_NONE, &o_update, "Update extensions", "extension" }, + { NULL }, + }; + GError *e = NULL; + GOptionContext *ctx = g_option_context_new(NULL); + g_option_context_add_main_entries(ctx, options, NULL); + if (!g_option_context_parse(ctx, &argc, &argv, &e) || missing) { + if (missing) + fprintf(stderr, "Missing argument\n"); + else + fprintf(stderr, "%s\n", missing ? "" : e->message); + fprintf(stderr, g_option_context_get_help(ctx, false, NULL)); + return 1; + } + + session = soup_session_sync_new(); + m_user_dir = g_build_filename(g_get_user_data_dir(), "dwb", "extensions", NULL); + check_dir(m_user_dir); + char *config_dir = g_build_filename(g_get_user_config_dir(), "dwb", "userscripts", NULL); + check_dir(config_dir); + m_loader = g_build_filename(config_dir, "extension_loader.js", NULL); + g_free(config_dir); + + m_meta_data = g_build_filename(m_user_dir, ".metadata", NULL); + m_installed = g_build_filename(m_user_dir, ".installed", NULL); + m_system_dir = g_build_filename("/usr", "share", "dwb", "extensions", NULL); + m_editor = g_getenv("EDITOR"); + if (m_editor == NULL) + m_editor = "vim"; + m_diff = g_getenv("DIFF_VIEWER"); + if (m_diff == NULL) + m_diff = "vimdiff"; + + if (o_bind) + flags |= F_BIND; + if (o_noconfig) + flags |= F_NO_CONFIG; + + if (o_update) { + cl_update(flags); + } + if (o_setbind != NULL) { + for (int i=0; o_setbind[i]; i++) + change_config(o_setbind[i], flags | F_BIND); + } + if (o_disable != NULL) { + for (int i=0; o_disable[i]; i++) + cl_disable(o_disable[i]); + } + if (o_enable != NULL) { + for (int i=0; o_enable[i]; i++) + cl_enable(o_enable[i]); + } + if (o_setload != NULL) { + for (int i=0; o_setload[i]; i++) + change_config(o_setload[i], flags & ~F_BIND); + } + if (o_install != NULL) { + for (int i=0; o_install[i]; i++) + cl_install(o_install[i], flags); + } + if (o_remove != NULL) { + for (int i=0; o_remove[i]; i++) + cl_uninstall(o_remove[i]); + } + g_free(m_user_dir); + g_free(m_meta_data); + g_free(m_system_dir); + g_free(m_loader); + g_object_unref(session); + return 0; +} |