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