Changed a few messages
[idzebra-moved-to-github.git] / util / res.c
1 /* $Id: res.c,v 1.32 2002-09-09 09:35:48 adam Exp $
2    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
3    Index Data Aps
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #ifdef WIN32
29 #include <io.h>
30 #else
31 #include <unistd.h>
32 #endif
33
34 #include <zebrautl.h>
35 #include <yaz/yaz-util.h>
36
37 struct res_entry {
38     char *name;
39     char *value;
40     struct res_entry *next;
41 };
42
43 struct res_struct {
44     struct res_entry *first, *last;
45     char *name;
46     int  init;
47     Res def_res;
48 };
49
50 static struct res_entry *add_entry (Res r)
51 {
52     struct res_entry *resp;
53
54     if (!r->first)
55         resp = r->last = r->first =
56             (struct res_entry *) xmalloc (sizeof(*resp));
57     else
58     {
59         resp = (struct res_entry *) 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 fr_buf[1024];
74     FILE *fr;
75
76     assert (r);
77     r->init = 1;
78
79     val_buf = (char*) xmalloc (val_max);
80
81     fr = fopen (r->name, "r");
82     if (!fr)
83     {
84         logf (LOG_WARN|LOG_ERRNO, "Cannot open `%s'", r->name);
85         return ;
86     }
87     while (1)
88     {
89         line = fgets (fr_buf, sizeof(fr_buf)-1, fr);
90         if (!line)
91             break;
92         if (*line == '#')
93         {
94             int no = 0;
95
96             while (fr_buf[no] && fr_buf[no] != '\n')
97                 no++;
98             fr_buf[no] = '\0';
99
100             resp = add_entry (r);
101             resp->name = (char*) xmalloc (no+1);
102             resp->value = NULL;
103             strcpy (resp->name, fr_buf);
104         }
105         else
106         {
107             int no = 0;
108             while (1)
109             {
110                 if (fr_buf[no] == 0 || fr_buf[no] == '\n' )
111                 {
112                     no = 0;
113                     break;
114                 }
115                 if (strchr (": \t", fr_buf[no]))
116                     break;
117                 no++;
118             }
119             if (!no)
120                 continue;
121             fr_buf[no++] = '\0';
122             resp = add_entry (r);
123             resp->name = (char*) xmalloc (no);
124             strcpy (resp->name, fr_buf);
125             
126             while (strchr (" \t", fr_buf[no]))
127                 no++;
128             val_size = 0;
129             while (1)
130             {
131                 if (fr_buf[no] == '\0' || strchr("\n\r\f", fr_buf[no]))
132                 {
133                     while (val_size > 0 &&
134                               (val_buf[val_size-1] == ' ' ||
135                                val_buf[val_size-1] == '\t'))
136                         val_size--;
137                     val_buf[val_size++] = '\0';
138                     resp->value = (char*) xmalloc (val_size);
139                     strcpy (resp->value, val_buf);
140                     logf (LOG_DEBUG, "(name=%s,value=%s)",
141                          resp->name, resp->value);
142                     break;
143                 }
144                 else if (fr_buf[no] == '\\' && strchr ("\n\r\f", fr_buf[no+1]))
145                 {
146                     line = fgets (fr_buf, sizeof(fr_buf)-1, fr);
147                     if (!line)
148                     {
149                         resp->value = (char*) xmalloc (val_size);
150                         strcpy (resp->value, val_buf);
151                         break;
152                     }
153                     no = 0;
154                 }
155                 else
156                 {
157                     val_buf[val_size++] = fr_buf[no++];
158                     if (val_size+1 >= val_max)
159                     {
160                         char *nb;
161
162                         nb = (char*) xmalloc (val_max+=1024);
163                         memcpy (nb, val_buf, val_size);
164                         xfree (val_buf);
165                         val_buf = nb;
166                     }
167                 }
168             }
169         }
170     }                
171     xfree (val_buf);
172     fclose (fr);
173 }
174
175 Res res_open (const char *name, Res def_res)
176 {
177     Res r;
178 #ifdef WIN32
179     if (access (name, 4))
180 #else
181     if (access (name, R_OK))
182 #endif
183     {
184         logf (LOG_WARN|LOG_ERRNO, "Cannot open `%s'", name);
185         return 0;
186     }
187     r = (Res) xmalloc (sizeof(*r));
188     r->init = 0;
189     r->first = r->last = NULL;
190     r->name = xstrdup (name);
191     r->def_res = def_res;
192     return r;
193 }
194
195 void res_close (Res r)
196 {
197     if (!r)
198         return;
199     if (r->init)
200     {
201         struct res_entry *re, *re1;
202         for (re = r->first; re; re=re1)
203         {
204             if (re->name)
205                 xfree (re->name);
206             if (re->value)
207                 xfree (re->value);
208             re1 = re->next;
209             xfree (re);
210         }
211     }
212     xfree (r->name);
213     xfree (r);
214 }
215
216 char *res_get (Res r, const char *name)
217 {
218     struct res_entry *re;
219
220     if (!r)
221         return 0;
222     if (!r->init)
223         reread (r);
224     for (re = r->first; re; re=re->next)
225         if (re->value && !yaz_matchstr (re->name, name))
226             return re->value;
227
228     return res_get (r->def_res, name);
229 }
230
231 char *res_get_def (Res r, const char *name, char *def)
232 {
233     char *t;
234
235     if (!(t = res_get (r, name)))
236     {
237         logf (LOG_DEBUG, "CAUTION: Using default resource %s:%s", name, def);
238         return def;
239     }
240     else
241         return t;
242 }
243
244 int res_get_match (Res r, const char *name, const char *value, const char *s)
245 {
246     const char *cn = res_get (r, name);
247
248     if (!cn)
249         cn = s;
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 int res_trav (Res r, const char *prefix, void *p,
275               void (*f)(void *p, const char *name, const char *value))
276 {
277     struct res_entry *re;
278     int l = 0;
279     int no = 0;
280     
281     if (!r)
282         return 0;
283     if (prefix)
284         l = strlen(prefix);
285     if (!r->init)
286         reread (r);
287     for (re = r->first; re; re=re->next)
288         if (re->value)
289             if (l==0 || !memcmp (re->name, prefix, l))
290             {
291                 (*f)(p, re->name, re->value);
292                 no++;
293             }
294     if (!no)
295         return res_trav (r->def_res, prefix, p, f);
296     return no;
297 }
298
299
300 int res_write (Res r)
301 {
302     struct res_entry *re;
303     FILE *fr;
304
305     assert (r);
306     if (!r->init)
307         reread (r);
308     fr = fopen (r->name, "w");
309     if (!fr)
310     {
311         logf (LOG_FATAL|LOG_ERRNO, "Cannot create `%s'", r->name);
312         exit (1);
313     }
314
315     for (re = r->first; re; re=re->next)
316     {
317         int no = 0;
318         int lefts = strlen(re->name)+2;
319
320         if (!re->value)
321             fprintf (fr, "%s\n", re->name);
322         else
323         {
324             fprintf (fr, "%s: ", re->name);
325             while (lefts + strlen(re->value+no) > 78)
326             {
327                 int i = 20;
328                 int ind = no+ 78-lefts;
329                 while (--i >= 0)
330                 {
331                     if (re->value[ind] == ' ')
332                         break;
333                     --ind;
334                 }
335                 if (i<0)
336                     ind = no + 78 - lefts;
337                 for (i = no; i != ind; i++)
338                     putc (re->value[i], fr);
339                 fprintf (fr, "\\\n");
340                 no=ind;
341                 lefts = 0;
342             }
343             fprintf (fr, "%s\n", re->value+no);
344         }
345     }
346     fclose (fr);
347     return 0;
348 }
349
350
351