(linenum→info "unix/slp.c:2238")

anthy/9100e/src-diclib/conf.c

    1: /*
    2:  * Anthyの設定のデータベース
    3:  * conf_initで設定される変数とconf_overrideで設定される
    4:  * 変数の関係に注意
    5:  *
    6:  * Copyright (C) 2000-2007 TABATA Yusuke
    7:  */
    8: /*
    9:   This library is free software; you can redistribute it and/or
   10:   modify it under the terms of the GNU Lesser General Public
   11:   License as published by the Free Software Foundation; either
   12:   version 2 of the License, or (at your option) any later version.
   13: 
   14:   This library is distributed in the hope that it will be useful,
   15:   but WITHOUT ANY WARRANTY; without even the implied warranty of
   16:   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   17:   Lesser General Public License for more details.
   18: 
   19:   You should have received a copy of the GNU Lesser General Public
   20:   License along with this library; if not, write to the Free Software
   21:   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
   22:  */
   23: #include <unistd.h>
   24: #include <pwd.h>
   25: #include <time.h>
   26: #include <sys/types.h>
   27: #include <stdlib.h>
   28: #include <stdio.h>
   29: #include <string.h>
   30: 
   31: #include <anthy/alloc.h>
   32: #include <anthy/conf.h>
   33: #include <anthy/logger.h>
   34: 
   35: #include <config.h>
   36: 
   37: /** 設定の変数と値 */
   38: struct val_ent {
   39:   /** 変数名 */
   40:   const char *var;
   41:   /** 値 */
   42:   const char *val;
   43:   /** リストの次要素 */
   44:   struct val_ent *next;
   45: };
   46: 
   47: static struct val_ent *ent_list;
   48: /** 初期化済みフラグ */
   49: static int confIsInit;
   50: static allocator val_ent_ator;
   51: 
   52: static void
   53: val_ent_dtor(void *p)
   54: {
   55:   struct val_ent *v = p;
   56:   free((void *)v->var);
   57:   if (v->val) {
   58:     free((void *)v->val);
   59:   }
   60: }
   61: 
   62: /** 変数名に対応するval_entを取得する */
   63: static struct val_ent *
   64: find_val_ent(const char *v)
   65: {
   66:   struct val_ent *e;
   67:   for (e = ent_list; e; e = e->next) {
   68:     if(!strcmp(v, e->var)) {
   69:       return e;
   70:     }
   71:   }
   72:   e = malloc(sizeof(struct val_ent));
   73:   if (!e) {
   74:     return NULL;
   75:   }
   76:   e->var = strdup(v);
   77:   e->val = 0;
   78:   e->next = ent_list;
   79:   ent_list = e;
   80:   return e;
   81: }
   82: 
   83: /** ${変数名}の形の変数の値を取得する
   84:  */
   85: static const char *
   86: get_subst(const char *s)
   87: {
   88:   if (s[0] == '$' && s[1] == '{' &&
   89:       strchr(s, '}')) {
   90:     struct val_ent *val;
   91:     char *var = strdup(&s[2]);
   92:     char *k = strchr(var, '}');
   93:     *k = 0;
   94:     val = find_val_ent(var);
   95:     free(var);
   96:     if (!val || !val->val) {
   97:       return "";
   98:     }
   99:     return val->val;
  100:   }
  101:   return NULL;
  102: }
  103: 
  104: struct expand_buf {
  105:   int len;
  106:   int size;
  107:   char *buf;
  108:   char *cur;
  109: };
  110: 
  111: static void
  112: ensure_buffer(struct expand_buf *eb, int count)
  113: {
  114:   int required = count - (eb->size - eb->len) + 16;
  115:   if (required > 0) {
  116:     eb->size += required;
  117:     eb->buf = realloc(eb->buf, eb->size);
  118:     eb->cur = &eb->buf[eb->len];
  119:   }
  120: }
  121: 
  122: static char *
  123: expand_string(const char *s)
  124: {
  125:   struct expand_buf eb;
  126:   char *res;
  127:   eb.size = 256;
  128:   eb.buf = malloc(eb.size);
  129:   eb.cur = eb.buf;
  130:   eb.len = 0;
  131: 
  132:   while (*s) {
  133:     const char *subst = get_subst(s);
  134:     if (subst) {
  135:       int len = strlen(subst);
  136:       ensure_buffer(&eb, len + 1);
  137:       *eb.cur = 0;
  138:       strcat(eb.buf, subst);
  139:       eb.cur += len;
  140:       eb.len += len;
  141:       s = strchr(s, '}');
  142:       s ++;
  143:     } else {
  144:       *eb.cur = *s;
  145:       /**/
  146:       eb.cur ++;
  147:       s++;
  148:       eb.len ++;
  149:     }
  150:     /**/
  151:     ensure_buffer(&eb, 256);
  152:   }
  153:   *eb.cur = 0;
  154:   /**/
  155:   res = strdup(eb.buf);
  156:   free(eb.buf);
  157:   return res;
  158: }
  159: 
  160: static void
  161: add_val(const char *var, const char *val)
  162: {
  163:   struct val_ent *e;
  164:   e = find_val_ent(var);
  165:   if (e->val) {
  166:     free((void *)e->val);
  167:   }
  168:   e->val = expand_string(val);
  169: }
  170: 
  171: static void
  172: read_conf_file(void)
  173: {
  174:   const char *fn;
  175:   FILE *fp;
  176:   char buf[1024];
  177:   fn = anthy_conf_get_str("CONFFILE");
  178:   fp = fopen(fn, "r");
  179:   if (!fp){
  180:     anthy_log(0, "Failed to open %s\n", fn);
  181:     return ;
  182:   }
  183:   while(fgets(buf, 1024, fp)) {
  184:     if (buf[0] != '#') {
  185:       char var[1024], val[1024];
  186:       if (sscanf(buf, "%s %s", var, val) == 2){
  187:         add_val(var, val);
  188:       }
  189:     }
  190:   }
  191:   fclose(fp);
  192: }
  193: 
  194: void
  195: anthy_do_conf_override(const char *var, const char *val)
  196: {
  197:   if (!strcmp(var,"CONFFILE")) {
  198:     add_val(var, val);
  199:     anthy_do_conf_init();
  200:   }else{
  201:     anthy_do_conf_init();
  202:     add_val(var, val);
  203:   }
  204: }
  205: 
  206: /* ユニークなセッションIDを確保する */
  207: #define SID_FORMAT      "%s-%08x-%05d" /* HOST-TIME-PID */
  208: #define MAX_SID_LEN     (MAX_HOSTNAME+8+5+2)
  209: #define MAX_HOSTNAME    64
  210: 
  211: static void
  212: alloc_session_id(void)
  213: {
  214:   time_t t;
  215:   pid_t pid;
  216:   char hn[MAX_HOSTNAME];
  217:   char sid[MAX_SID_LEN];
  218:   t = time(0);
  219:   pid = getpid();
  220:   gethostname(hn, MAX_HOSTNAME);
  221:   hn[MAX_HOSTNAME-1] = '\0';
  222:   sprintf(sid, SID_FORMAT, hn, (unsigned int)t & 0xffffffff, pid & 0xffff);
  223:   add_val("SESSION-ID", sid);
  224: }
  225: 
  226: void
  227: anthy_do_conf_init(void)
  228: {
  229: 
  230:   if (!confIsInit) {
  231:     const char *fn;
  232:     struct passwd *pw;
  233:     val_ent_ator = anthy_create_allocator(sizeof(struct val_ent), val_ent_dtor);
  234:     /*デフォルトの値を設定する。*/
  235:     add_val("VERSION", VERSION);
  236:     fn = anthy_conf_get_str("CONFFILE");
  237:     if (!fn){
  238:       add_val("CONFFILE", CONF_DIR"/anthy-conf");
  239:     }
  240:     pw = getpwuid(getuid());
  241:     add_val("HOME", pw->pw_dir);
  242:     alloc_session_id();
  243:     read_conf_file();
  244:     confIsInit = 1;
  245:   }
  246: }
  247: 
  248: void
  249: anthy_conf_free(void)
  250: {
  251:   struct val_ent *e, *next;
  252:   for (e = ent_list; e; e = next) {
  253:     free((char *)e->var);
  254:     free((char *)e->val);
  255:     next = e->next;
  256:     free(e);
  257:   }
  258:   ent_list = NULL;
  259:   confIsInit = 0;
  260: }
  261: 
  262: const char *
  263: anthy_conf_get_str(const char *var)
  264: {
  265:   struct val_ent *e;
  266:   e = find_val_ent(var);
  267:   return e->val;
  268: }
Syntax (Markdown)