1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
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:
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:
207: #define SID_FORMAT "%s-%08x-%05d"
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: }