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