/[Development]/lmsd/inifile.c
ViewVC logotype

Contents of /lmsd/inifile.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.1 - (show annotations) (download)
Mon Apr 14 22:20:47 2003 UTC (7 years, 4 months ago) by lukasz
Branch: MAIN
CVS Tags: HEAD
File MIME type: text/plain
- recovery from source (after crash-test of cvs)
1
2 /* stolen from TGT, here is the original header: */
3
4 /* ----------------------------------------------------------------------------
5 ** config.c Configuration file reading routines
6 ** ----------------------------------------------------------------------------
7 ** TGT TextGUIToolkit Library
8 ** Copyright (C) 2000-2001 Mateusz Golicz and Tomasz Sterna
9 **
10 ** LGPL license
11 **
12 ** ----------------------------------------------------------------------------
13 ** MAINTAINER Mateusz Golicz
14 **
15 ** Log:
16 ** - cleanup
17 **
18 */
19
20
21 #include <pwd.h>
22 #include <sys/types.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include "inifile.h"
29
30 int isblank (int c); /* does not appear in my libc includes !! */
31
32 static int ini_conf_hash(char *str)
33 {
34 int i,l,r;
35 for(i=0,l=strlen(str),r=0;i<l;i++) r=(r << 1) + str[i];
36 return(r % HASH_SIZE);
37 }
38
39 /*
40 *
41 * ini_get_conf: Get a configuration variable from given config object
42 *
43 */
44
45 char* ini_get_conf(struct ini_prefs *prefs, /* Config object */
46 char *section, /* Section name */
47 char *key, /* Key name */
48 char *def) /* What to return if not found in file ? */
49 {
50 struct ini_section * sec;
51 struct ini_value * pair;
52 int k;
53
54 if(!prefs) return(def); /* We do not have any config object ! */
55
56 k=ini_conf_hash(section);
57 for(sec=prefs->sections[k];sec!=NULL;sec=sec->next)
58 if(strcmp(section,sec->name)==0) break; /* look for section of given name */
59
60 if(!sec) return(def); /* there is no such section */
61
62 k=ini_conf_hash(key);
63 for(pair=sec->pairs[k];pair!=NULL;pair=pair->next)
64 if(strcmp(key,pair->key)==0) break; /* look for key of given name */
65
66 if(!pair) return(def); /* there is no such key */
67 return(pair->string); /* return value associated with that key */
68 }
69
70 /*
71 *
72 * ini_set_conf: Set a configuration variable in given config object
73 *
74 */
75
76 int ini_set_conf(struct ini_prefs *prefs,
77 char* section,
78 char* key,
79 char* value)
80 {
81 int k,ret,i;
82 struct ini_section *sec;
83 struct ini_value *pair;
84
85 k=ini_conf_hash(section); ret=0;
86 for(sec=prefs->sections[k];sec!=NULL;sec=sec->next)
87 if(strcmp(section,sec->name)==0) break;
88 /* look for given section */
89
90 if(!sec) /* no such section .. */
91 {
92 // ret|=CONF_NOTICE_NOSUCHSECTION; /* notify the caller, that it had to be created */
93 sec=(struct ini_section*) malloc(sizeof(struct ini_section));
94 sec->name=strdup(section); /* copy the section name */
95 for(i=0;i<HASH_SIZE;i++) sec->pairs[i]=NULL; /* zero its items hash table */
96 sec->next=prefs->sections[k]; /* link into list */
97 prefs->sections[k]=sec;
98 }
99
100 k=ini_conf_hash(key);
101 for(pair=sec->pairs[k];pair!=NULL;pair=pair->next)
102 if(strcmp(key,pair->key)==0) break;
103 /* look for given key */
104
105 if(!pair) /* no such key .. */
106 {
107 // ret|=CONF_NOTICE_NOSUCHKEY; /* notify the caller */
108 pair=(struct ini_value*) malloc(sizeof(struct ini_value));
109 pair->key=strdup(key); /* copy the key name */
110 pair->next=sec->pairs[k];
111 sec->pairs[k]=pair; /* link it into list */
112 }
113 else
114 free(pair->string); /* free old value */
115
116 pair->string=strdup(value); /* copy new key value */
117
118 return(ret); /* return status */
119 }
120
121 /*
122 *
123 * ini_reparse: Change weird characters in string to escape/special sequences
124 *
125 */
126 unsigned char *ini_reparse(unsigned char *string)
127 {
128 unsigned char *ret;
129 unsigned char c,d,e;
130 int l,i,k;
131
132 l=strlen(string);
133 ret=(unsigned char*) malloc(l*4+2); /* in the worst case we'll need so much */
134 for(i=0,k=0;i<l;i++) /* foreach character in string */
135 {
136 c=string[i];
137 if(!isprint(c)) /* it's nonprintable */
138 {
139 d=c >> 4; e=c & 0xf; /* change it to hex digits */
140 if(d<10) d+='0'; else d=d+'a'-10;
141 if(e<10) e+='0'; else e=e+'a'-10; /* and transform to ascii */
142
143 ret[k++]='\\'; ret[k++]='x'; ret[k++]=d; ret[k++]=e;
144 /* write the sequence to the final string */
145 }
146 else
147 {
148 if(c=='\\' || c=='"') /* it's a special character */
149 {
150 ret[k++]='\\'; ret[k++]=c; /* escape it with \ and write into the final string */
151 }
152 else
153 ret[k++]=c; /* leave it alone */
154 }
155 }
156 ret[k++]=0;
157 ret=(char*) realloc(ret, k);
158 return(ret);
159 }
160
161 /*
162 *
163 * ini_parse: Process special sequences in strings (\ and \x..)
164 *
165 */
166 unsigned char *ini_parse(unsigned char *string,int *length,unsigned char terminator)
167 {
168 unsigned char *out;
169 unsigned char c,d,e;
170 int i,k;
171
172 out=(char*) malloc(strlen(string)); k=0; /* in the worst case we'll need so much */
173 for(i=0;string[i]!=0;i++) /* foreach character in string */
174 {
175 if(string[i]=='\\') /* is it '\' ? */
176 {
177 c=string[i+1]; /* get next character .. */
178 if(!c) continue; /* if it's end of string, forget that */
179 if(c=='n')
180 {
181 out[k++] = '\n'; i++;
182 continue;
183 }
184 if(c=='x') /* x - means hexadecimal code of character */
185 {
186 if((d=string[i+2])) /* get first hex digit */
187 {
188 if((e=string[i+3])) /* get second hex digit */
189 {
190 if(d>='a' && d<='f') d=d-'a'+10; else d-='0';
191 if(e>='a' && e<='f') e=e-'a'+10; else e-='0';
192 out[k++]=d << 4 | e; /* calculate character code and write into final string */
193 i+=3; /* x<hex_digit><hex_digit> */
194 continue;
195 }
196 }
197 }
198 out[k++]=c; i++; /* just an escaped character */
199 }
200 else
201 {
202 if(string[i]==terminator) break; /* we reached end of string */
203 out[k++]=string[i]; /* add that end marker to final string */
204 }
205 }
206 out[k]=0;
207 if(length) *length=i;
208 return(out);
209 }
210
211 /*
212 *
213 * ini_compresstr: Remove spaces from string
214 *
215 */
216 char * ini_compressstr(char *a)
217 {
218 int i,k,l;
219 char *ret;
220 ret=(char*) malloc(l=strlen(a));
221 for(i=0,k=0;i<l;i++) if(!isspace(a[i])) ret[k++]=a[i];
222 ret[k]=0;
223 ret=(char*) realloc(ret,k+1);
224 return(ret);
225 }
226
227 /*
228 *
229 * ini_unload_conf: Free all memory associated with internal config file structures
230 *
231 */
232
233 void ini_unload_conf(struct ini_prefs * prefs)
234 {
235 int i,j;
236 struct ini_section *a,*p;
237 struct ini_value *b,*q;
238 for(i=0;i<HASH_SIZE;i++)
239 {
240 for(a=prefs->sections[i];a;a=p)
241 {
242 for(j=0;j<HASH_SIZE;j++)
243 {
244 for(b=a->pairs[j];b;b=q)
245 {
246 q=b->next;
247 free(b->key);
248 free(b->string);
249 free(b);
250 }
251 }
252 p=a->next;
253 free(a->name);
254 free(a);
255 }
256 }
257 free(prefs);
258 }
259
260 /*
261 *
262 * ini_save_conf: Save internal config file structures into a real file
263 *
264 */
265
266 int ini_save_conf(struct ini_prefs * prefs,char *filename)
267 {
268 int i,j;
269 char *str;
270 FILE *fh;
271 struct ini_section *a;
272 struct ini_value *b;
273
274 if(!(fh=fopen(filename,"w"))) return(0);
275 fprintf(fh,"# Auto-generated by config.o/libtgt.so , Written 2000-2001 by Tomasz Sterna & Mateusz Golicz\n");
276 /* write copyright */
277
278 for(i=0;i<HASH_SIZE;i++)
279 for(a=prefs->sections[i];a;a=a->next)
280 {
281 fprintf(fh,"[%s]\n",a->name); /* Section name */
282 for(j=0;j<HASH_SIZE;j++)
283 for(b=a->pairs[j];b;b=b->next) /* foreach pair */
284 {
285 fprintf(fh,"%s = \"%s\"\n",b->key,str=ini_reparse(b->string));
286 free(str);
287 }
288 }
289
290 fclose(fh);
291 return(1);
292 }
293
294 /*
295 *
296 * ini_load_conf: Load configuration file and store it in internal structures
297 *
298 */
299
300 struct ini_prefs * ini_load_conf(char *name)
301 {
302 FILE *fh;
303 char *file,*mem,*hdir;
304 struct ini_prefs *ret;
305 int i,size,seclen,keylen,l;
306 char *section;
307 char *value,*key;
308 struct passwd *pentry;
309
310 ret=(struct ini_prefs*) malloc(sizeof(struct ini_prefs)); /* allocate global object */
311 for(i=0;i<HASH_SIZE;i++) ret->sections[i]=NULL; /* and clean it's Section Hash Table */
312
313 if(!(fh=fopen(name,"r"))) /* try opening the file in cwd */
314 if(!fh) { free(ret); return(NULL); }
315
316 fseek(fh,0,SEEK_END); size=ftell(fh); rewind(fh); /* get file size */
317 mem=file=(char*) malloc(size+1); file[size]=0;
318 fread(file,size,1,fh); /* load whole file into memory */
319 fclose(fh); /* and close it */
320
321 section=strdup("main"); /* the name of current section */
322 for(;;) /* parse loop */
323 {
324 for(;isblank(*file) || *file=='\n' || *file=='\r';file++);
325 /* skip all white spaces / enters */
326 if(!(*file)) break; /* EOF ? */
327 if(*file=='#' || *file==';')
328 {
329 if(!(file=index(file,'\n'))) break; /* a comment, skip to EOL */
330 continue;
331 }
332 if(*file=='[') /* New section */
333 {
334 for(seclen=0;file[seclen]!=']' && file[seclen]!=0;seclen++); /* get section length */
335 if(!(file[seclen]))
336 {
337 fprintf(stderr,"ini_load_conf(): Parse error: unable to find matching ']'\n");
338 break;
339 }
340 if(section) free(section); /* free old section name */
341 section=(char*) malloc(seclen);
342 snprintf(section,seclen,"%s",file+1); /* compose new one ...*/
343 file+=seclen+1;
344 continue;
345 }
346 /* it's an assignement then */
347 for(keylen=0;file[keylen]!='=' && file[keylen]!=0;keylen++);
348 /* get the length of everything before '=' ... */
349 if(file[keylen]==0) break; /* eof ? */
350 key=file; key[keylen]=0; file+=keylen+1; /* make a key string */
351 for(;isblank(*file);file++); /* skip all spaces after = */
352 if(*file=='"') /* quoted string */
353 {
354 int vl;
355
356 value=ini_parse(file+1,&l,'"'); /* find matching " and fetch that string */
357 if(file[1]==0 || file[2]==0) break;
358 file+=l+2;
359 }
360 else
361 {
362 value=ini_parse(file,&l,'\n'); /* if it's not quoted, then skip to EOL */
363 file+=l;
364 }
365
366 key=ini_compressstr(key); /* remove spaces in string before = */
367 ini_set_conf(ret,section,key,value); /* and pass it as a key to setconf function */
368 free(value); free(key); /* free temporary strings */
369 }
370 free(mem); free(section); /* clean up */
371 return(ret);
372 }

CVS Admin
ViewVC Help
Powered by ViewVC 1.1.6