diff options
Diffstat (limited to 'src-diclib/conf.c')
-rw-r--r-- | src-diclib/conf.c | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/src-diclib/conf.c b/src-diclib/conf.c new file mode 100644 index 0000000..7299cff --- /dev/null +++ b/src-diclib/conf.c @@ -0,0 +1,268 @@ +/* + * Anthyの設定のデータベース + * conf_initで設定される変数とconf_overrideで設定される + * 変数の関係に注意 + * + * Copyright (C) 2000-2007 TABATA Yusuke + */ +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <unistd.h> +#include <pwd.h> +#include <time.h> +#include <sys/types.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <anthy/alloc.h> +#include <anthy/conf.h> +#include <anthy/logger.h> + +#include <config.h> + +/** 設定の変数と値 */ +struct val_ent { + /** 変数名 */ + const char *var; + /** 値 */ + const char *val; + /** リストの次要素 */ + struct val_ent *next; +}; + +static struct val_ent *ent_list; +/** 初期化済みフラグ */ +static int confIsInit; +static allocator val_ent_ator; + +static void +val_ent_dtor(void *p) +{ + struct val_ent *v = p; + free((void *)v->var); + if (v->val) { + free((void *)v->val); + } +} + +/** 変数名に対応するval_entを取得する */ +static struct val_ent * +find_val_ent(const char *v) +{ + struct val_ent *e; + for (e = ent_list; e; e = e->next) { + if(!strcmp(v, e->var)) { + return e; + } + } + e = malloc(sizeof(struct val_ent)); + if (!e) { + return NULL; + } + e->var = strdup(v); + e->val = 0; + e->next = ent_list; + ent_list = e; + return e; +} + +/** ${変数名}の形の変数の値を取得する + */ +static const char * +get_subst(const char *s) +{ + if (s[0] == '$' && s[1] == '{' && + strchr(s, '}')) { + struct val_ent *val; + char *var = strdup(&s[2]); + char *k = strchr(var, '}'); + *k = 0; + val = find_val_ent(var); + free(var); + if (!val || !val->val) { + return ""; + } + return val->val; + } + return NULL; +} + +struct expand_buf { + int len; + int size; + char *buf; + char *cur; +}; + +static void +ensure_buffer(struct expand_buf *eb, int count) +{ + int required = count - (eb->size - eb->len) + 16; + if (required > 0) { + eb->size += required; + eb->buf = realloc(eb->buf, eb->size); + eb->cur = &eb->buf[eb->len]; + } +} + +static char * +expand_string(const char *s) +{ + struct expand_buf eb; + char *res; + eb.size = 256; + eb.buf = malloc(eb.size); + eb.cur = eb.buf; + eb.len = 0; + + while (*s) { + const char *subst = get_subst(s); + if (subst) { + int len = strlen(subst); + ensure_buffer(&eb, len + 1); + *eb.cur = 0; + strcat(eb.buf, subst); + eb.cur += len; + eb.len += len; + s = strchr(s, '}'); + s ++; + } else { + *eb.cur = *s; + /**/ + eb.cur ++; + s++; + eb.len ++; + } + /**/ + ensure_buffer(&eb, 256); + } + *eb.cur = 0; + /**/ + res = strdup(eb.buf); + free(eb.buf); + return res; +} + +static void +add_val(const char *var, const char *val) +{ + struct val_ent *e; + e = find_val_ent(var); + if (e->val) { + free((void *)e->val); + } + e->val = expand_string(val); +} + +static void +read_conf_file(void) +{ + const char *fn; + FILE *fp; + char buf[1024]; + fn = anthy_conf_get_str("CONFFILE"); + fp = fopen(fn, "r"); + if (!fp){ + anthy_log(0, "Failed to open %s\n", fn); + return ; + } + while(fgets(buf, 1024, fp)) { + if (buf[0] != '#') { + char var[1024], val[1024]; + if (sscanf(buf, "%s %s", var, val) == 2){ + add_val(var, val); + } + } + } + fclose(fp); +} + +void +anthy_do_conf_override(const char *var, const char *val) +{ + if (!strcmp(var,"CONFFILE")) { + add_val(var, val); + anthy_do_conf_init(); + }else{ + anthy_do_conf_init(); + add_val(var, val); + } +} + +/* ユニークなセッションIDを確保する */ +#define SID_FORMAT "%s-%08x-%05d" /* HOST-TIME-PID */ +#define MAX_SID_LEN (MAX_HOSTNAME+8+5+2) +#define MAX_HOSTNAME 64 + +static void +alloc_session_id(void) +{ + time_t t; + pid_t pid; + char hn[MAX_HOSTNAME]; + char sid[MAX_SID_LEN]; + t = time(0); + pid = getpid(); + gethostname(hn, MAX_HOSTNAME); + hn[MAX_HOSTNAME-1] = '\0'; + sprintf(sid, SID_FORMAT, hn, (unsigned int)t & 0xffffffff, pid & 0xffff); + add_val("SESSION-ID", sid); +} + +void +anthy_do_conf_init(void) +{ + + if (!confIsInit) { + const char *fn; + struct passwd *pw; + val_ent_ator = anthy_create_allocator(sizeof(struct val_ent), val_ent_dtor); + /*デフォルトの値を設定する。*/ + add_val("VERSION", VERSION); + fn = anthy_conf_get_str("CONFFILE"); + if (!fn){ + add_val("CONFFILE", CONF_DIR"/anthy-conf"); + } + pw = getpwuid(getuid()); + add_val("HOME", pw->pw_dir); + alloc_session_id(); + read_conf_file(); + confIsInit = 1; + } +} + +void +anthy_conf_free(void) +{ + struct val_ent *e, *next; + for (e = ent_list; e; e = next) { + free((char *)e->var); + free((char *)e->val); + next = e->next; + free(e); + } + ent_list = NULL; + confIsInit = 0; +} + +const char * +anthy_conf_get_str(const char *var) +{ + struct val_ent *e; + e = find_val_ent(var); + return e->val; +} |