Bug fix.
[idzebra-moved-to-github.git] / util / res.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: res.c,v $
7  * Revision 1.12  1995-01-24 16:40:32  adam
8  * Bug fix.
9  *
10  * Revision 1.11  1994/10/05  16:54:52  adam
11  * Minor changes.
12  *
13  * Revision 1.10  1994/10/05  10:47:31  adam
14  * Small bug fix.
15  *
16  * Revision 1.9  1994/09/16  14:41:12  quinn
17  * Added log warning to res_get_def
18  *
19  * Revision 1.8  1994/09/16  14:37:12  quinn
20  * added res_get_def
21  *
22  * Revision 1.7  1994/09/06  13:01:03  quinn
23  * Removed const from declaration of res_get
24  *
25  * Revision 1.6  1994/09/01  17:45:14  adam
26  * Work on resource manager.
27  *
28  * Revision 1.5  1994/08/18  11:02:28  adam
29  * Implementation of res_write.
30  *
31  * Revision 1.4  1994/08/18  10:02:01  adam
32  * Module alexpath moved from res.c to alexpath.c. Minor changes in res-test.c
33  *
34  * Revision 1.3  1994/08/18  09:43:51  adam
35  * Development of resource manager. Only missing is res_write.
36  *
37  * Revision 1.2  1994/08/18  08:23:26  adam
38  * Res.c now use handles. xmalloc defines xstrdup.
39  *
40  * Revision 1.1  1994/08/17  15:34:23  adam
41  * Initial version of resource manager.
42  *
43  */
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <assert.h>
48 #include <unistd.h>
49 #include <util.h>
50
51 static struct res_entry *add_entry (Res r)
52 {
53     struct res_entry *resp;
54
55     if (!r->first)
56         resp = r->last = r->first = xmalloc (sizeof(*resp));
57     else
58     {
59         resp = xmalloc (sizeof(*resp));
60         r->last->next = resp;
61         r->last = resp;
62     }
63     resp->next = NULL;
64     return resp;
65 }
66
67 static void reread (Res r)
68 {
69     struct res_entry *resp;
70     char *line;
71     char *val_buf;
72     int val_size, val_max = 256;
73     char path[256];
74     char fr_buf[1024];
75     FILE *fr;
76
77     assert (r);
78     r->init = 1;
79
80     val_buf = xmalloc (val_max);
81
82     strcpy (path, alex_path(r->name));
83
84     fr = fopen (path, "r");
85     if (!fr)
86     {
87         log (LOG_FATAL|LOG_ERRNO, "Cannot open %s", path);
88         exit (1);
89     }
90     while (1)
91     {
92         line = fgets (fr_buf, 1023, fr);
93         if (!line)
94             break;
95         if (*line == '#')
96         {
97             int no = 0;
98
99             while (fr_buf[no] && fr_buf[no] != '\n')
100                 no++;
101             fr_buf[no] = '\0';
102
103             resp = add_entry (r);
104             resp->name = xmalloc (no+1);
105             resp->value = NULL;
106             strcpy (resp->name, fr_buf);
107         }
108         else
109         {
110             int no = 0;
111             while (1)
112             {
113                 if (fr_buf[no] == 0 || fr_buf[no] == '\n' )
114                 {
115                     no = -1;
116                     break;
117                 }
118                 if (fr_buf[no] == ':')
119                     break;
120                 no++;
121             }
122             if (no < 0)
123                 continue;
124             fr_buf[no++] = '\0';
125             resp = add_entry (r);
126             resp->name = xmalloc (no);
127             strcpy (resp->name, fr_buf);
128             
129             while (fr_buf[no] == ' ')
130                 no++;
131             val_size = 0;
132             while (1)
133             {
134                 if (fr_buf[no] == '\0' || fr_buf[no] == '\n')
135                 {
136                     val_buf[val_size++] = '\0';
137                     resp->value = xmalloc (val_size);
138                     strcpy (resp->value, val_buf);
139                     log (LOG_DEBUG, "(name=%s,value=%s)",
140                          resp->name, resp->value);
141                     break;
142                 }
143                 else if (fr_buf[no] == '\\' && fr_buf[no+1] == '\n')
144                 {
145                     line = fgets (fr_buf, 1023, fr);
146                     if (!line)
147                     {
148                         resp->value = xmalloc (val_size);
149                         strcpy (resp->value, val_buf);
150                         break;
151                     }
152                     no = 0;
153                 }
154                 else
155                 {
156                     val_buf[val_size++] = fr_buf[no++];
157                     if (val_size+1 >= val_max)
158                     {
159                         char *nb;
160
161                         nb = xmalloc (val_max+=1024);
162                         memcpy (nb, val_buf, val_size);
163                         xfree (val_buf);
164                         val_buf = nb;
165                     }
166                 }
167             }
168         }
169     }                
170     xfree (val_buf);
171     fclose (fr);
172 }
173
174 Res res_open (const char *name)
175 {
176     Res r;
177     if (access (name, R_OK))
178         log (LOG_LOG|LOG_ERRNO, "Cannot access `%s'", name);
179     r = xmalloc (sizeof(*r));
180     r->init = 0;
181     r->first = r->last = NULL;
182     r->name = xstrdup (name);
183     return r;
184 }
185
186 void res_close (Res r)
187 {
188     assert (r);
189     if (r->init)
190     {
191         struct res_entry *re, *re1;
192         for (re = r->first; re; re=re1)
193         {
194             if (re->name)
195                 xfree (re->name);
196             if (re->value)
197                 xfree (re->value);
198             re1 = re->next;
199             xfree (re);
200         }
201     }
202     xfree (r);
203 }
204
205 char *res_get (Res r, const char *name)
206 {
207     struct res_entry *re;
208
209     assert (r);
210     if (!r->init)
211         reread (r);
212     for (re = r->first; re; re=re->next)
213         if (re->value && !strcmp (re->name, name))
214             return re->value;
215     return NULL;
216 }
217
218 char *res_get_def (Res r, const char *name, char *def)
219 {
220     char *t;
221
222     if (!(t = res_get (r, name)))
223     {
224         log(LOG_DEBUG, "CAUTION: Using default resource %s:%s", name, def);
225         return def;
226     }
227     else
228         return t;
229 }
230
231 void res_put (Res r, const char *name, const char *value)
232 {
233     struct res_entry *re;
234     assert (r);
235     if (!r->init)
236         reread (r);
237
238     for (re = r->first; re; re=re->next)
239         if (re->value && !strcmp (re->name, name))
240         {
241             xfree (re->value);
242             re->value = xstrdup (value);
243             return;
244         }
245     re = add_entry (r);
246     re->name = xstrdup (name);
247     re->value = xstrdup (value);
248 }
249
250 void res_trav (Res r, const char *prefix, 
251                void (*f)(const char *name, const char *value))
252 {
253     struct res_entry *re;
254     int l = 0;
255
256     assert (r);
257     if (prefix)
258         l = strlen(prefix);
259     if (!r->init)
260         reread (r);
261     for (re = r->first; re; re=re->next)
262         if (re->value)
263             if (l==0 || !memcmp (re->name, prefix, l))
264                 (*f)(re->name, re->value);
265 }
266
267
268 int res_write (Res r)
269 {
270     struct res_entry *re;
271     char path[256];
272     FILE *fr;
273
274     assert (r);
275     if (!r->init)
276         reread (r);
277     strcpy (path, alex_path(r->name));
278
279     fr = fopen (path, "w");
280     if (!fr)
281     {
282         log (LOG_FATAL|LOG_ERRNO, "Cannot create %s", path);
283         exit (1);
284     }
285
286     for (re = r->first; re; re=re->next)
287     {
288         int no = 0;
289         int lefts = strlen(re->name)+2;
290
291         if (!re->value)
292             fprintf (fr, "%s\n", re->name);
293         else
294         {
295             fprintf (fr, "%s: ", re->name);
296             while (lefts + strlen(re->value+no) > 78)
297             {
298                 int i = 20;
299                 int ind = no+ 78-lefts;
300                 while (--i >= 0)
301                 {
302                     if (re->value[ind] == ' ')
303                         break;
304                     --ind;
305                 }
306                 if (i<0)
307                     ind = no + 78 - lefts;
308                 for (i = no; i != ind; i++)
309                     putc (re->value[i], fr);
310                 fprintf (fr, "\\\n");
311                 no=ind;
312                 lefts = 0;
313             }
314             fprintf (fr, "%s\n", re->value+no);
315         }
316     }
317     fclose (fr);
318     return 0;
319 }
320
321
322