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