From: Steven Luo Date: Tue, 25 May 2010 13:41:42 +0000 (-0700) Subject: Refactor configuration X-Git-Tag: v3.3b1~16 X-Git-Url: http://git.maemo.org/git/?p=browser-switch;a=commitdiff_plain;h=ec8b58af1b1cf22f34478faf476047e7ce996245;hp=ebfd6218aa25d59ce3fcc2330ca62a77c6c754f8 Refactor configuration Most of the code for loading configuration from the config file was being duplicated between the UI and the main browser-switchboard code; also, the forthcoming command-line configuration tool should share the code for loading and saving configuration with the UI. Therefore, move code for loading and saving configuration information into functions generic enough to be shared between the UIs and browser-switchboard. --- diff --git a/Makefile b/Makefile index 65bb61e..e6e1bb8 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ LDFLAGS = -Wl,--as-needed `pkg-config --libs dbus-glib-1` $(EXTRA_LDFLAGS) PREFIX = /usr APP = browser-switchboard -obj = main.o launcher.o dbus-server-bindings.o configfile.o log.o +obj = main.o launcher.o dbus-server-bindings.o config.o configfile.o log.o all: @echo 'Usage:' diff --git a/config-ui/Makefile b/config-ui/Makefile index 8bc3749..b6a7d17 100644 --- a/config-ui/Makefile +++ b/config-ui/Makefile @@ -11,14 +11,14 @@ LDFLAGS_PLUGIN = -shared $(LDFLAGS_HILDON) \ `pkg-config --libs libosso` `pkg-config --libs hildon-control-panel` PREFIX = /usr -other_obj = ../configfile.o +other_obj = ../configfile.o ../config.o save-config.o APP = browser-switchboard-cp app_obj = $(APP).app.o $(other_obj) HILDON_APP = $(APP)-hildon happ_obj = $(APP).happ.o $(other_obj) PLUGIN = lib$(APP).so -plugin_obj = $(APP).plugin.o ../configfile.plugin.o +plugin_obj = $(APP).plugin.o ../configfile.plugin.o ../config.plugin.o save-config.plugin.o all: @echo 'Usage:' diff --git a/config-ui/browser-switchboard-cp.c b/config-ui/browser-switchboard-cp.c index 1b16242..6866c84 100644 --- a/config-ui/browser-switchboard-cp.c +++ b/config-ui/browser-switchboard-cp.c @@ -51,7 +51,7 @@ #endif /* HILDON_CP_APPLET */ #endif /* HILDON */ -#include "configfile.h" +#include "config.h" #define CONTINUOUS_MODE_DEFAULT 0 @@ -73,7 +73,7 @@ struct browser_entry browsers[] = { { NULL, NULL }, }; -char *logger_name = NULL; +struct swb_config orig_cfg; struct config_widgets { #if defined(HILDON) && defined(FREMANTLE) @@ -152,170 +152,36 @@ static inline void set_other_browser_cmd(char *cmd) { } static void load_config(void) { - FILE *fp; - int continuous_mode_seen = 0; - int default_browser_seen = 0; - int other_browser_cmd_seen = 0; - struct swb_config_line line; - - if (!(fp = open_config_file())) - return; - - /* Parse the config file - TODO: should we handle errors differently than EOF? */ - if (!parse_config_file_begin()) - goto out; - while (!parse_config_file_line(fp, &line)) { - if (line.parsed) { - if (!strcmp(line.key, "continuous_mode")) { - if (!continuous_mode_seen) { - set_continuous_mode(atoi(line.value)); - continuous_mode_seen = 1; - } - free(line.value); - } else if (!strcmp(line.key, "default_browser")) { - if (!default_browser_seen) { - set_default_browser(line.value); - default_browser_seen = 1; - } - free(line.value); - } else if (!strcmp(line.key, "other_browser_cmd")) { - if (!other_browser_cmd_seen) { - set_other_browser_cmd(line.value); - other_browser_cmd_seen = 1; - } - free(line.value); - } else if (!strcmp(line.key, "logging")) { - if (!logger_name) - logger_name = line.value; - } - } - free(line.key); - } - parse_config_file_end(); - -out: - fclose(fp); - return; + swb_config_init(&orig_cfg); + + swb_config_load(&orig_cfg); + + set_continuous_mode(orig_cfg.continuous_mode); + set_default_browser(orig_cfg.default_browser); + if (orig_cfg.other_browser_cmd) + set_other_browser_cmd(orig_cfg.other_browser_cmd); } static void save_config(void) { - FILE *fp = NULL, *tmpfp = NULL; - char *homedir, *tempfile, *newfile; - size_t len; - int continuous_mode_seen = 0; - int default_browser_seen = 0; - int other_browser_cmd_seen = 0; - struct swb_config_line line; - - /* If CONFIGFILE_DIR doesn't exist already, try to create it */ - if (!(homedir = getenv("HOME"))) - homedir = DEFAULT_HOMEDIR; - len = strlen(homedir) + strlen(CONFIGFILE_DIR) + 1; - if (!(newfile = calloc(len, sizeof(char)))) - return; - snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_DIR); - if (access(newfile, F_OK) == -1 && errno == ENOENT) { - mkdir(newfile, 0750); + struct swb_config new_cfg = orig_cfg; + + if (get_continuous_mode() != orig_cfg.continuous_mode) { + new_cfg.continuous_mode = get_continuous_mode(); + new_cfg.flags |= SWB_CONFIG_CONTINUOUS_MODE_SET; } - free(newfile); - - /* Put together the path to the new config file and the tempfile */ - len = strlen(homedir) + strlen(CONFIGFILE_LOC) + 1; - if (!(newfile = calloc(len, sizeof(char)))) - return; - /* 4 = strlen(".tmp") */ - if (!(tempfile = calloc(len+4, sizeof(char)))) { - free(newfile); - return; + if (strcmp(get_default_browser(), orig_cfg.default_browser)) { + new_cfg.default_browser = get_default_browser(); + new_cfg.flags |= SWB_CONFIG_DEFAULT_BROWSER_SET; } - snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_LOC); - snprintf(tempfile, len+4, "%s%s", newfile, ".tmp"); - - /* Open the temporary file for writing */ - if (!(tmpfp = fopen(tempfile, "w"))) - /* TODO: report the error somehow? */ - goto out; - - /* Open the old config file, if it exists */ - if ((fp = open_config_file()) && parse_config_file_begin()) { - /* Copy the old config file over to the new one line by line, - replacing old config values with new ones - TODO: should we handle errors differently than EOF? */ - while (!parse_config_file_line(fp, &line)) { - if (line.parsed) { - /* Is a config line, print the new value here */ - if (!strcmp(line.key, "continuous_mode")) { - if (!continuous_mode_seen) { - fprintf(tmpfp, "%s = %d\n", - line.key, - get_continuous_mode()); - continuous_mode_seen = 1; - } - } else if (!strcmp(line.key, - "default_browser")) { - if (!default_browser_seen) { - fprintf(tmpfp, "%s = \"%s\"\n", - line.key, - get_default_browser()); - default_browser_seen = 1; - } - } else if (!strcmp(line.key, - "other_browser_cmd")) { - if (!other_browser_cmd_seen && - strlen(get_other_browser_cmd())>0) { - fprintf(tmpfp, "%s = \"%s\"\n", - line.key, - get_other_browser_cmd()); - other_browser_cmd_seen = 1; - } - } else if (!strcmp(line.key, - "logging")) { - if (logger_name) { - fprintf(tmpfp, "%s = \"%s\"\n", - line.key, - logger_name); - free(logger_name); - logger_name = NULL; - } - } - } else { - /* Just copy the old line over */ - fprintf(tmpfp, "%s\n", line.key); - } - free(line.key); - free(line.value); - } - parse_config_file_end(); + if ((orig_cfg.other_browser_cmd && + strcmp(get_other_browser_cmd(), orig_cfg.other_browser_cmd)) || + (!orig_cfg.other_browser_cmd && + strlen(get_other_browser_cmd()) > 0)) { + new_cfg.other_browser_cmd = get_other_browser_cmd(); + new_cfg.flags |= SWB_CONFIG_OTHER_BROWSER_CMD_SET; } - /* If we haven't written them yet, write out the new config values */ - if (!continuous_mode_seen) - fprintf(tmpfp, "%s = %d\n", - "continuous_mode", get_continuous_mode()); - if (!default_browser_seen) - fprintf(tmpfp, "%s = \"%s\"\n", - "default_browser", get_default_browser()); - if (!other_browser_cmd_seen && strlen(get_other_browser_cmd()) > 0) - fprintf(tmpfp, "%s = \"%s\"\n", - "other_browser_cmd", get_other_browser_cmd()); - if (logger_name) - fprintf(tmpfp, "%s = \"%s\"\n", - "logging", logger_name); - - /* Replace the old config file with the new one */ - fclose(tmpfp); - tmpfp = NULL; - rename(tempfile, newfile); - -out: - free(newfile); - free(tempfile); - if (tmpfp) - fclose(tmpfp); - if (fp) - fclose(fp); - return; + swb_config_save(&new_cfg); } static void do_reconfig(void) { diff --git a/config-ui/save-config.c b/config-ui/save-config.c new file mode 100644 index 0000000..6b010e5 --- /dev/null +++ b/config-ui/save-config.c @@ -0,0 +1,162 @@ +/* + * save-config.c -- functions to save a Browser Switchboard configuration + * + * Copyright (C) 2009-2010 Steven Luo + * Derived from a Python implementation by Jason Simpson and Steven Luo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include +#include +#include +#include +#include + +#include "configfile.h" +#include "config.h" + +/* Save the settings in the provided swb_config struct to the config file + Returns true on success, false otherwise */ +int swb_config_save(struct swb_config *cfg) { + FILE *fp = NULL, *tmpfp = NULL; + char *homedir, *tempfile, *newfile; + size_t len; + int retval = 1; + struct swb_config_line line; + unsigned int oldcfg_seen = 0; + + /* If CONFIGFILE_DIR doesn't exist already, try to create it */ + if (!(homedir = getenv("HOME"))) + homedir = DEFAULT_HOMEDIR; + len = strlen(homedir) + strlen(CONFIGFILE_DIR) + 1; + if (!(newfile = calloc(len, sizeof(char)))) + return 0; + snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_DIR); + if (access(newfile, F_OK) == -1 && errno == ENOENT) { + mkdir(newfile, 0750); + } + free(newfile); + + /* Put together the path to the new config file and the tempfile */ + len = strlen(homedir) + strlen(CONFIGFILE_LOC) + 1; + if (!(newfile = calloc(len, sizeof(char)))) + return 0; + /* 4 = strlen(".tmp") */ + if (!(tempfile = calloc(len+4, sizeof(char)))) { + free(newfile); + return 0; + } + snprintf(newfile, len, "%s%s", homedir, CONFIGFILE_LOC); + snprintf(tempfile, len+4, "%s%s", newfile, ".tmp"); + + /* Open the temporary file for writing */ + if (!(tmpfp = fopen(tempfile, "w"))) { + retval = 0; + goto out; + } + + /* Open the old config file, if it exists */ + if ((fp = open_config_file()) && parse_config_file_begin()) { + /* Copy the old config file over to the new one line by line, + replacing old config values with new ones + TODO: should we handle errors differently than EOF? */ + while (!parse_config_file_line(fp, &line)) { + if (line.parsed) { + /* Is a config line, print the new value here */ + if (!strcmp(line.key, "continuous_mode")) { + if (!(oldcfg_seen & + SWB_CONFIG_CONTINUOUS_MODE_SET)) { + fprintf(tmpfp, "%s = %d\n", + line.key, + cfg->continuous_mode); + oldcfg_seen |= + SWB_CONFIG_CONTINUOUS_MODE_SET; + } + } else if (!strcmp(line.key, + "default_browser")) { + if (!(oldcfg_seen & + SWB_CONFIG_DEFAULT_BROWSER_SET)) { + fprintf(tmpfp, "%s = \"%s\"\n", + line.key, + cfg->default_browser); + oldcfg_seen |= + SWB_CONFIG_DEFAULT_BROWSER_SET; + } + } else if (!strcmp(line.key, + "other_browser_cmd")) { + if (!(oldcfg_seen & + SWB_CONFIG_OTHER_BROWSER_CMD_SET)) { + fprintf(tmpfp, "%s = \"%s\"\n", + line.key, + cfg->other_browser_cmd); + oldcfg_seen |= + SWB_CONFIG_OTHER_BROWSER_CMD_SET; + } + } else if (!strcmp(line.key, + "logging")) { + if (!(oldcfg_seen & + SWB_CONFIG_LOGGING_SET)) { + fprintf(tmpfp, "%s = \"%s\"\n", + line.key, + cfg->logging); + oldcfg_seen |= + SWB_CONFIG_LOGGING_SET; + } + } + } else { + /* Just copy the old line over */ + fprintf(tmpfp, "%s\n", line.key); + } + free(line.key); + free(line.value); + } + parse_config_file_end(); + } + + /* If we haven't written them yet, write out any new config values */ + if (!(oldcfg_seen & SWB_CONFIG_CONTINUOUS_MODE_SET) && + (cfg->flags & SWB_CONFIG_CONTINUOUS_MODE_SET)) + fprintf(tmpfp, "%s = %d\n", + "continuous_mode", cfg->continuous_mode); + if (!(oldcfg_seen & SWB_CONFIG_DEFAULT_BROWSER_SET) && + (cfg->flags & SWB_CONFIG_DEFAULT_BROWSER_SET)) + fprintf(tmpfp, "%s = \"%s\"\n", + "default_browser", cfg->default_browser); + if (!(oldcfg_seen & SWB_CONFIG_OTHER_BROWSER_CMD_SET) && + (cfg->flags & SWB_CONFIG_OTHER_BROWSER_CMD_SET)) + fprintf(tmpfp, "%s = \"%s\"\n", + "other_browser_cmd", cfg->other_browser_cmd); + if (!(oldcfg_seen & SWB_CONFIG_LOGGING_SET) && + (cfg->flags & SWB_CONFIG_LOGGING_SET)) + fprintf(tmpfp, "%s = \"%s\"\n", + "logging", cfg->logging); + + /* Replace the old config file with the new one */ + fclose(tmpfp); + tmpfp = NULL; + rename(tempfile, newfile); + +out: + free(newfile); + free(tempfile); + if (tmpfp) + fclose(tmpfp); + if (fp) + fclose(fp); + return retval; +} diff --git a/config.c b/config.c new file mode 100644 index 0000000..663858a --- /dev/null +++ b/config.c @@ -0,0 +1,125 @@ +/* + * config.c -- configuration functions for Browser Switchboard + * + * Copyright (C) 2009-2010 Steven Luo + * Derived from a Python implementation by Jason Simpson and Steven Luo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#include +#include + +#include "configfile.h" +#include "config.h" + +/* Initialize a swb_config struct with configuration defaults */ +void swb_config_init(struct swb_config *cfg) { + if (!cfg) + return; + + cfg->continuous_mode = 0; + cfg->default_browser = "microb"; + cfg->other_browser_cmd = NULL; + cfg->logging = "stdout"; + + cfg->flags = SWB_CONFIG_INITIALIZED; +} + +/* Free all heap memory used in an swb_config struct + This MUST NOT be done if any of the strings are being used elsewhere! */ +void swb_config_free(struct swb_config *cfg) { + if (!cfg) + return; + if (!(cfg->flags & SWB_CONFIG_INITIALIZED)) + return; + + if (cfg->flags & SWB_CONFIG_DEFAULT_BROWSER_SET) { + free(cfg->default_browser); + cfg->default_browser = NULL; + } + if (cfg->flags & SWB_CONFIG_OTHER_BROWSER_CMD_SET) { + free(cfg->other_browser_cmd); + cfg->other_browser_cmd = NULL; + } + if (cfg->flags & SWB_CONFIG_LOGGING_SET) { + free(cfg->logging); + cfg->logging = NULL; + } + + cfg->flags = 0; +} + +/* Read the config file and load settings into the provided swb_config struct + Caller is responsible for freeing allocated strings with free() + Returns true on success, false otherwise */ +int swb_config_load(struct swb_config *cfg) { + FILE *fp; + struct swb_config_line line; + + if (!cfg || !(cfg->flags & SWB_CONFIG_INITIALIZED)) + return 0; + + if (!(fp = open_config_file())) + goto out_noopen; + + /* Parse the config file + TODO: should we handle errors differently than EOF? */ + if (!parse_config_file_begin()) + goto out; + while (!parse_config_file_line(fp, &line)) { + if (line.parsed) { + if (!strcmp(line.key, "continuous_mode")) { + if (!(cfg->flags & + SWB_CONFIG_CONTINUOUS_MODE_SET)) { + cfg->continuous_mode = atoi(line.value); + cfg->flags |= + SWB_CONFIG_CONTINUOUS_MODE_SET; + } + free(line.value); + } else if (!strcmp(line.key, "default_browser")) { + if (!(cfg->flags & + SWB_CONFIG_DEFAULT_BROWSER_SET)) { + cfg->default_browser = line.value; + cfg->flags |= + SWB_CONFIG_DEFAULT_BROWSER_SET; + } + } else if (!strcmp(line.key, "other_browser_cmd")) { + if (!(cfg->flags & + SWB_CONFIG_OTHER_BROWSER_CMD_SET)) { + cfg->other_browser_cmd = line.value; + cfg->flags |= + SWB_CONFIG_OTHER_BROWSER_CMD_SET; + } + } else if (!strcmp(line.key, "logging")) { + if (!(cfg->flags & SWB_CONFIG_LOGGING_SET)) { + cfg->logging = line.value; + cfg->flags |= SWB_CONFIG_LOGGING_SET; + } + } else { + /* Don't need this line's contents */ + free(line.value); + } + } + free(line.key); + } + parse_config_file_end(); + +out: + fclose(fp); +out_noopen: + return 1; +} diff --git a/config.h b/config.h new file mode 100644 index 0000000..39df717 --- /dev/null +++ b/config.h @@ -0,0 +1,47 @@ +/* + * config.h -- definitions for Browser Switchboard configuration + * + * Copyright (C) 2009-2010 Steven Luo + * Derived from a Python implementation by Jason Simpson and Steven Luo + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +#ifndef _CONFIG_H +#define _CONFIG_H + +#define SWB_CONFIG_INITIALIZED 0x01 +#define SWB_CONFIG_CONTINUOUS_MODE_SET 0x02 +#define SWB_CONFIG_DEFAULT_BROWSER_SET 0x04 +#define SWB_CONFIG_OTHER_BROWSER_CMD_SET 0x08 +#define SWB_CONFIG_LOGGING_SET 0x10 + +struct swb_config { + unsigned int flags; + int continuous_mode; + char *default_browser; + char *other_browser_cmd; + char *logging; +}; + +void swb_config_init(struct swb_config *cfg); +void swb_config_free(struct swb_config *cfg); + +int swb_config_load(struct swb_config *cfg); + +int swb_config_save(struct swb_config *cfg); + +#endif /* _CONFIG_H */ diff --git a/main.c b/main.c index 093b535..30361c8 100644 --- a/main.c +++ b/main.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -30,82 +31,41 @@ #include "browser-switchboard.h" #include "launcher.h" #include "dbus-server-bindings.h" -#include "configfile.h" +#include "config.h" #include "log.h" struct swb_context ctx; -static void set_config_defaults(struct swb_context *ctx) { - if (!ctx) - return; - free(ctx->other_browser_cmd); - ctx->continuous_mode = 0; - ctx->default_browser_launcher = NULL; - ctx->other_browser_cmd = NULL; -} - static void waitforzombies(int signalnum) { while (waitpid(-1, NULL, WNOHANG) > 0) log_msg("Waited for a zombie\n"); } static void read_config(int signalnum) { - FILE *fp; - int continuous_mode_seen = 0; - struct swb_config_line line; - char *default_browser = NULL, *logger_name = NULL; - - set_config_defaults(&ctx); - - if (!(fp = open_config_file())) - goto out_noopen; - - /* Parse the config file - TODO: should we handle errors differently than EOF? */ - if (!parse_config_file_begin()) - goto out; - while (!parse_config_file_line(fp, &line)) { - if (line.parsed) { - if (!strcmp(line.key, "continuous_mode")) { - if (!continuous_mode_seen) { - ctx.continuous_mode = atoi(line.value); - continuous_mode_seen = 1; - } - free(line.value); - } else if (!strcmp(line.key, "default_browser")) { - if (!default_browser) - default_browser = line.value; - } else if (!strcmp(line.key, "other_browser_cmd")) { - if (!ctx.other_browser_cmd) - ctx.other_browser_cmd = line.value; - } else if (!strcmp(line.key, "logging")) { - if (!logger_name) - logger_name = line.value; - } else { - /* Don't need this line's contents */ - free(line.value); - } - } - free(line.key); - } - parse_config_file_end(); + struct swb_config cfg; -out: - fclose(fp); -out_noopen: - log_config(logger_name); - update_default_browser(&ctx, default_browser); + swb_config_init(&cfg); + + swb_config_load(&cfg); + + log_config(cfg.logging); + ctx.continuous_mode = cfg.continuous_mode; + if (cfg.other_browser_cmd) { + if (!(ctx.other_browser_cmd = strdup(cfg.other_browser_cmd))) { + log_perror(errno, "Failed to set other_browser_cmd"); + exit(1); + } + } else + ctx.other_browser_cmd = NULL; + update_default_browser(&ctx, cfg.default_browser); - log_msg("continuous_mode: %d\n", ctx.continuous_mode); - log_msg("default_browser: '%s'\n", - default_browser?default_browser:"NULL"); + log_msg("continuous_mode: %d\n", cfg.continuous_mode); + log_msg("default_browser: '%s'\n", cfg.default_browser); log_msg("other_browser_cmd: '%s'\n", - ctx.other_browser_cmd?ctx.other_browser_cmd:"NULL"); - log_msg("logging: '%s'\n", - logger_name?logger_name:"NULL"); + cfg.other_browser_cmd?cfg.other_browser_cmd:"NULL"); + log_msg("logging: '%s'\n", cfg.logging); - free(logger_name); - free(default_browser); + swb_config_free(&cfg); return; }