/* $Id: res.c,v 1.37.2.1 2004/11/26 11:06:13 adam Exp $
Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002,2003,2004
Index Data Aps
This file is part of the Zebra server.
Zebra is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with Zebra; see the file LICENSE.zebra. If not, write to the
Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#ifdef WIN32
#include <io.h>
#else
#include <unistd.h>
#endif
#include <zebrautl.h>
struct res_entry {
char *name;
char *value;
struct res_entry *next;
};
struct res_struct {
struct res_entry *first, *last;
char *name;
int init;
Res def_res;
Res over_res;
};
static struct res_entry *add_entry (Res r)
{
struct res_entry *resp;
if (!r->first)
resp = r->last = r->first =
(struct res_entry *) xmalloc (sizeof(*resp));
else
{
resp = (struct res_entry *) xmalloc (sizeof(*resp));
r->last->next = resp;
r->last = resp;
}
resp->next = NULL;
return resp;
}
static char *xstrdup_env(const char *src)
{
int i = 0;
int j = 0;
char *dst;
int env_strlen = 0;
while (src[i])
{
if (src[i] == '$' && src[i+1] == '{')
{
char envname[128];
char *env_val;
int k = 0;
i = i + 2;
while (k < 127 && src[i] && !strchr(":}\n\r\f", src[i]))
envname[k++] = src[i++];
envname[k] = '\0';
env_val = getenv(envname);
if (env_val)
env_strlen += 1 + strlen(env_val);
else
env_strlen++;
while (src[i] && !strchr("}\n\r\f", src[i]))
i++;
if (src[i] == '}')
i++;
}
else
i++;
}
dst = xmalloc(1 + env_strlen + i);
i = 0;
while (src[i])
{
if (src[i] == '$' && src[i+1] == '{')
{
char envname[128];
char *env_val;
int k = 0;
i = i + 2;
while(k < 127 && src[i] && !strchr(":}\n\r\f", src[i]))
envname[k++] = src[i++];
envname[k] = '\0';
env_val = getenv(envname);
if (env_val)
{
strcpy(dst+j, env_val);
j += strlen(env_val);
}
else if (src[i] == ':' && src[i+1] == '-')
{
i = i + 2;
while (src[i] && !strchr("}\n\r\f", src[i]))
dst[j++] = src[i++];
}
while (src[i] && !strchr("}\n\r\f", src[i]))
i++;
if (src[i] == '}')
i++;
}
else
dst[j++] = src[i++];
}
dst[j] = '\0';
return dst;
}
static void reread (Res r)
{
struct res_entry *resp;
char *line;
char *val_buf;
int val_size, val_max = 256;
char fr_buf[1024];
FILE *fr;
assert (r);
r->init = 1;
if (!r->name)
return;
fr = fopen (r->name, "r");
if (!fr)
{
logf (LOG_WARN|LOG_ERRNO, "Cannot open `%s'", r->name);
return ;
}
val_buf = (char*) xmalloc (val_max);
while (1)
{
line = fgets (fr_buf, sizeof(fr_buf)-1, fr);
if (!line)
break;
if (*line == '#')
{
int no = 0;
while (fr_buf[no] && fr_buf[no] != '\n')
no++;
fr_buf[no] = '\0';
resp = add_entry (r);
resp->name = (char*) xmalloc (no+1);
resp->value = NULL;
strcpy (resp->name, fr_buf);
}
else
{
int no = 0;
while (1)
{
if (fr_buf[no] == 0 || fr_buf[no] == '\n' )
{
no = 0;
break;
}
if (strchr (": \t", fr_buf[no]))
break;
no++;
}
if (!no)
continue;
fr_buf[no++] = '\0';
resp = add_entry (r);
resp->name = (char*) xmalloc (no);
strcpy (resp->name, fr_buf);
while (strchr (" \t", fr_buf[no]))
no++;
val_size = 0;
while (1)
{
if (fr_buf[no] == '\0' || strchr("\n\r\f", fr_buf[no]))
{
while (val_size > 0 &&
(val_buf[val_size-1] == ' ' ||
val_buf[val_size-1] == '\t'))
val_size--;
val_buf[val_size] = '\0';
resp->value = xstrdup_env(val_buf);
logf (LOG_DEBUG, "(name=%s,value=%s)",
resp->name, resp->value);
break;
}
else if (fr_buf[no] == '\\' && strchr ("\n\r\f", fr_buf[no+1]))
{
line = fgets (fr_buf, sizeof(fr_buf)-1, fr);
if (!line)
{
val_buf[val_size] = '\0';
resp->value = xstrdup_env(val_buf);
break;
}
no = 0;
}
else
{
val_buf[val_size++] = fr_buf[no++];
if (val_size+1 >= val_max)
{
char *nb;
nb = (char*) xmalloc (val_max+=1024);
memcpy (nb, val_buf, val_size);
xfree (val_buf);
val_buf = nb;
}
}
}
}
}
xfree (val_buf);
fclose (fr);
}
Res res_open (const char *name, Res def_res, Res over_res)
{
Res r;
if (name)
{
#ifdef WIN32
if (access (name, 4))
#else
if (access (name, R_OK))
#endif
{
logf (LOG_WARN|LOG_ERRNO, "Cannot open `%s'", name);
return 0;
}
}
r = (Res) xmalloc (sizeof(*r));
r->init = 0;
r->first = r->last = NULL;
if (name)
r->name = xstrdup (name);
else
r->name=0;
r->def_res = def_res;
r->over_res = over_res;
return r;
}
void res_close (Res r)
{
if (!r)
return;
if (r->init)
{
struct res_entry *re, *re1;
for (re = r->first; re; re=re1)
{
if (re->name)
xfree (re->name);
if (re->value)
xfree (re->value);
re1 = re->next;
xfree (re);
}
}
xfree (r->name);
xfree (r);
}
const char *res_get_prefix (Res r, const char *name, const char *prefix,
const char *def)
{
const char *v = 0;;
if (prefix)
{
char rname[128];
if (strlen(name) + strlen(prefix) >= (sizeof(rname)-2))
return 0;
strcpy(rname, prefix);
strcat(rname, ".");
strcat(rname, name);
v = res_get(r, rname);
}
if (!v)
v = res_get(r, name);
if (!v)
v = def;
return v;
}
const char *res_get (Res r, const char *name)
{
struct res_entry *re;
const char *v;
if (!r)
return 0;
v = res_get(r->over_res, name);
if (v)
return v;
if (!r->init)
reread (r);
for (re = r->first; re; re=re->next)
if (re->value && !yaz_matchstr (re->name, name))
return re->value;
return res_get (r->def_res, name);
}
const char *res_get_def (Res r, const char *name, const char *def)
{
const char *t;
if (!(t = res_get (r, name)))
{
logf (LOG_DEBUG, "CAUTION: Using default resource %s:%s", name, def);
return def;
}
else
return t;
}
int res_get_match (Res r, const char *name, const char *value, const char *s)
{
const char *cn = res_get (r, name);
if (!cn)
cn = s;
if (cn && !yaz_matchstr (cn, value))
return 1;
return 0;
}
void res_set (Res r, const char *name, const char *value)
{
struct res_entry *re;
assert (r);
if (!r->init)
reread (r);
for (re = r->first; re; re=re->next)
if (re->value && !yaz_matchstr (re->name, name))
{
xfree (re->value);
re->value = xstrdup_env (value);
return;
}
re = add_entry (r);
re->name = xstrdup (name);
re->value = xstrdup_env (value);
}
int res_trav (Res r, const char *prefix, void *p,
void (*f)(void *p, const char *name, const char *value))
{
struct res_entry *re;
int l = 0;
int no = 0;
if (!r)
return 0;
if (prefix)
l = strlen(prefix);
if (!r->init)
reread (r);
for (re = r->first; re; re=re->next)
if (re->value)
if (l==0 || !memcmp (re->name, prefix, l))
{
(*f)(p, re->name, re->value);
no++;
}
if (!no)
return res_trav (r->def_res, prefix, p, f);
return no;
}
int res_write (Res r)
{
struct res_entry *re;
FILE *fr;
assert (r);
if (!r->init)
reread (r);
if (!r->name)
return 0; /* ok, this was not from a file */
fr = fopen (r->name, "w");
if (!fr)
{
logf (LOG_FATAL|LOG_ERRNO, "Cannot create `%s'", r->name);
exit (1);
}
for (re = r->first; re; re=re->next)
{
int no = 0;
int lefts = strlen(re->name)+2;
if (!re->value)
fprintf (fr, "%s\n", re->name);
else
{
fprintf (fr, "%s: ", re->name);
while (lefts + strlen(re->value+no) > 78)
{
int i = 20;
int ind = no+ 78-lefts;
while (--i >= 0)
{
if (re->value[ind] == ' ')
break;
--ind;
}
if (i<0)
ind = no + 78 - lefts;
for (i = no; i != ind; i++)
putc (re->value[i], fr);
fprintf (fr, "\\\n");
no=ind;
lefts = 0;
}
fprintf (fr, "%s\n", re->value+no);
}
}
fclose (fr);
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1