diff options
Diffstat (limited to 'src/sms_config.c')
-rw-r--r-- | src/sms_config.c | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/src/sms_config.c b/src/sms_config.c new file mode 100644 index 0000000..79271a3 --- /dev/null +++ b/src/sms_config.c @@ -0,0 +1,361 @@ +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <termios.h> +#include <linux/limits.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> + +#include "global.h" + +#if HAVE_LIBYAML +#include <yaml.h> +#endif + +#include "atcmd.h" +#include "utils.h" +#include "log.h" + +#if HAVE_LIBYAML + +struct config_info { + yaml_parser_t parser; + char *filename; + FILE *file; + + yaml_event_t event; + + int map_level; + char *section; + char *key; + char *value; + + int complete; +}; + +static int boolean_value(const char *str) +{ + return !strcmp(str, "true") ? true : false; +} + +static int config_open(struct config_info *config, char *filename) +{ + int err; + + memset(config, 0, sizeof(*config)); + + config->filename = strdup(filename); + if (!config->filename) { + log_error("out of memory"); + } + + config->file = fopen(config->filename, "r"); + if (!config->file) { + log_error("open config %s: %m", config->filename); + return -1; + } + + err = yaml_parser_initialize(&config->parser); + if (!err) { + log_error("yaml_parser_initialize"); + fclose(config->file); + return -1; + } + + yaml_parser_set_input_file(&config->parser, config->file); + + config->complete = false; + + return 0; +} + +static int config_close(struct config_info *config) +{ + yaml_parser_delete(&config->parser); + fclose(config->file); + free(config->filename); + free(config->section); + free(config->key); + free(config->value); + + return 0; +} + +static int config_next_event(struct config_info *config) +{ + int err; + + err = yaml_parser_parse(&config->parser, &config->event); + if (!err) { + log_error("yaml parse error"); + return -1; + } + + return 0; +} + +static void config_delete_event(struct config_info *config) +{ + yaml_event_delete(&config->event); +} + +static int config_set_core_value(const char *key, const char *value) +{ + log_debug("try setting core.%s to %s", key, value); + + if (!strcmp("verbose", key)) { + Global.core.verbose = boolean_value(value); + } else if (!strcmp("interactive", key)) { + Global.core.interactive = boolean_value(value); + } else if (!strcmp("baud-rate", key)) { + Global.core.baud_rate = atoi(value); + Global.core.baud_rate = value_to_baud(Global.core.baud_rate); + } else if (!strcmp("read-timeout", key)) { + Global.core.read_timeout = atoi(value); + } else if (!strcmp("device", key)) { + Global.core.device = strdup(value); + } else if (!strcmp("msg-store-read", key)) { + Global.core.msg_store_read = strdup(value); + } else if (!strcmp("msg-store-send", key)) { + Global.core.msg_store_send = strdup(value); + } else if (!strcmp("msg-store-new", key)) { + Global.core.msg_store_new = strdup(value); + } else if (!strcmp("pb-store", key)) { + Global.core.pb_store = strdup(value); + } else if (!strcmp("editor", key)) { + Global.core.editor = strdup(value); + } else if (!strcmp("edit-file", key)) { + Global.core.edit_file = strdup(value); + } + + return 0; +} + +static int config_set_smtp_value(const char *key, const char *value) +{ + log_debug("try setting smtp.%s to '%s'", key, value); + + if (!strcmp("server", key)) { + Global.smtp.server = strdup(value); + } else if (!strcmp("port", key)) { + Global.smtp.port = atoi(value); + } else if (!strcmp("user", key)) { + Global.smtp.user = strdup(value); + } else if (!strcmp("passwd", key)) { + Global.smtp.passwd = strdup(value); + } else if (!strcmp("encryption", key)) { + Global.smtp.encryption = strdup(value); + } + + return 0; +} + +static int config_set_send_email_value(const char *key, const char *value) +{ + log_debug("try setting send-email.%s to %s", key, value); + + if (!strcmp("domain", key)) { + Global.send_email.domain = strdup(value); + } + + return 0; +} + +static int config_set_user_value(const char *key, const char *value) +{ + log_debug("try setting user.%s to %s", key, value); + + if (!strcmp("name", key)) { + Global.user.name = strdup(value); + } else if (!strcmp("email", key)) { + Global.user.email = strdup(value); + } + + return 0; +} + +static int config_handle_event(struct config_info *config) +{ + switch (config->event.type) { + case YAML_STREAM_START_EVENT: + return 0; + case YAML_STREAM_END_EVENT: + return 0; + case YAML_DOCUMENT_START_EVENT: + return 0; + case YAML_DOCUMENT_END_EVENT: + config->complete = true; + return 0; + + case YAML_SCALAR_EVENT: + if (config->map_level == 1) { + config->section = strdup((char *) config->event.data.scalar.value); + if (!config->section) { + log_error("out of memory"); + return -1; + } + log_debug("section: %s", config->section); + + return 0; + } else if (config->map_level != 2) { + log_debug("bad map level: %d", config->map_level); + return -1; + } + + if (!config->key) { + config->key = strdup((char *) config->event.data.scalar.value); + if (!config->key) { + log_error("out of memory"); + return -1; + } + + return 0; + } else if (!config->value) { + config->value = strdup((char *) config->event.data.scalar.value); + if (!config->value) { + log_error("out of memory"); + return -1; + } + } + + if (config->key && config->value) { + if (!strcmp(config->section, "core")) { + config_set_core_value(config->key, config->value); + } else if (!strcmp(config->section, "smtp")) { + config_set_smtp_value(config->key, config->value); + } else if (!strcmp(config->section, "send-email")) { + config_set_send_email_value(config->key, config->value); + } else if (!strcmp(config->section, "user")) { + config_set_user_value(config->key, config->value); + } + + free(config->key); + config->key = NULL; + + free(config->value); + config->value = NULL; + } + + return 0; + + case YAML_MAPPING_START_EVENT: + config->map_level++; + + return 0; + + case YAML_MAPPING_END_EVENT: + free(config->section); + config->section = NULL; + + free(config->key); + config->key = NULL; + + free(config->value); + config->value = NULL; + + config->map_level--; + + return 0; + + default: + log_error("event type: %d", config->event.type); + return -1; + } +} + +#define SMS_CONFIG_FILE ".smsconfig" +static int _sms_config_load(void) +{ + int err; + struct config_info config; + struct stat sbuf; + + err = stat(SMS_CONFIG_FILE, &sbuf); + if (err < 0) { + if (errno == ENOENT) { + log_notice("sms config file missing"); + return 0; + } + + return -1; + } + + err = config_open(&config, SMS_CONFIG_FILE); + if (err < 0) { + log_error("open config failed"); + return -1; + } + + while (1) { + err = config_next_event(&config); + if (err < 0) { + log_error("handle event failed"); + break; + } + + err = config_handle_event(&config); + if (err < 0) { + log_error("handle event failed"); + config_delete_event(&config); + break; + } + config_delete_event(&config); + + if (config.complete) { + break; + } + } + + int complete = config.complete; + + err = config_close(&config); + if (err < 0) { + log_error("close config failed"); + return -1; + } + + if (!complete) { + log_error("config load did not complete"); + return -1; + } + + log_debug("config loaded"); + + return 0; +} + +int sms_config_load(void) +{ + int err; + char *cp; + char prev[PATH_MAX]; + char *home; + + home = getenv("HOME"); + if (!home) { + log_error("HOME is not set"); + return -1; + } + + cp = getcwd(prev, sizeof(prev)); + if (!cp) { + log_error("getcwd %m"); + return -1; + } + + chdir(home); + + err = _sms_config_load(); + + chdir(prev); + + return err; +} +#else +int sms_config_load(void) +{ + return 0; +} +#endif |