/*
** Copyright 2000-2004 University of Illinois Board of Trustees
** Copyright 2000-2004 Mark D. Roth
** All rights reserved.
**
** serverlist.c - code to handle references to other PH servers
**
** Mark D. Roth <roth@feep.net>
*/
#include <internal.h>
#include <errno.h>
#ifdef STDC_HEADERS
# include <string.h>
# include <stdlib.h>
#endif
#include <strings.h>
/*
** ph_serverlist_add() - add an entry to a list of known PH servers.
** returns:
** 0 success
** -1 error (sets errno)
*/
int
ph_serverlist_add(struct ph_serverlist *serverlist, char *server, char *site)
{
void *ptr;
#ifdef DEBUG
printf("in ph_serverlist_add([serverlist], \"%s\", \"%s\")\n", server,
site);
#endif
ptr = realloc(serverlist->sl_list,
(serverlist->sl_numservers + 2) * sizeof(struct ph_serversite));
if (ptr == NULL)
return -1;
serverlist->sl_list = (struct ph_serversite *)ptr;
memset(&(serverlist->sl_list[serverlist->sl_numservers + 1]),
0, sizeof(struct ph_serversite));
serverlist->sl_list[serverlist->sl_numservers].ss_server = strdup(server);
serverlist->sl_list[serverlist->sl_numservers].ss_site = strdup(site);
serverlist->sl_numservers++;
return 0;
}
/*
** ph_serverlist_iterate() - iterate through all matching PH server entries.
** returns:
** 1 data returned
** 0 no more data
** -1 error (sets errno)
*/
int
ph_serverlist_iterate(struct ph_serverlist *serverlist,
char *server, char *site,
struct ph_serversite **serversite)
{
char *p;
#ifdef DEBUG
printf("in ph_serverlist_iterate([serverlist], \"%s\", \"%s\", "
"0x%lx)\n",
(server ? server : "NULL"),
(site ? site : "NULL"),
*serversite);
#endif
if (server != NULL)
{
/* make sure it's at least two levels */
p = strchr(server, '.');
if (p == NULL || p == server || *(p + 1) == '\0')
{
errno = EINVAL;
return -1;
}
/* strip trailing '.' */
if (server[strlen(server) - 1] == '.')
server[strlen(server) - 1] = '\0';
}
if (*serversite == NULL)
*serversite = serverlist->sl_list;
else
(*serversite)++;
for (; (*serversite)->ss_site != NULL; (*serversite)++)
{
#ifdef DEBUG
printf("ph_serverlist_iterate(): checking server=\"%s\" "
"site=\"%s\"\n",
(*serversite)->ss_server, (*serversite)->ss_site);
#endif
/* match server name only on final set of domain components */
if (server != NULL)
{
p = (*serversite)->ss_server + strlen((*serversite)->ss_server) - strlen(server);
if (p < (*serversite)->ss_server
|| strcasecmp(p, server) != 0
|| (p != (*serversite)->ss_server
&& *(p - 1) != '.'))
continue;
}
/* match site on substring match */
if (site != NULL
&& strstr((*serversite)->ss_site, site) == NULL)
continue;
/* found a match */
return 1;
}
return 0;
}
/*
** ph_serverlist_merge() - read list of known PH servers from the server
** associated with ph and merge them into serverlist.
** returns:
** 0 success
** -1 error (sets errno)
** PH_ERR_DATAERR invalid query
*/
int
ph_serverlist_merge(PH *ph, struct ph_serverlist *serverlist)
{
char *site;
char *linep, *nextp, *typep;
int i, save_errno, numentries;
ph_memblock_t *blockp;
struct ph_fieldselector query[] = {
{ "name", '=', "ns-servers" },
{ "type", '=', "serverlist" },
{ NULL, '\0', NULL }
};
char *getfields[] = { "text", NULL };
ph_entry *entries;
/* get list of known servers */
if (ph_mmgr_malloc(ph->ph_mmgr, 0, 0, 0,
(ph_free_func_t)ph_free_entries,
&blockp) == -1)
return -1;
numentries = ph_query(ph, query, getfields,
(ph_entry **)&(ph_mmgr_ptr(blockp)));
if (numentries == PH_ERR_NOMATCH)
{
ph_mmgr_free(blockp, 1);
return 0;
}
if (numentries <= 0)
{
save_errno = errno;
ph_mmgr_free(blockp, 1);
errno = save_errno;
return numentries;
}
entries = (ph_entry *)ph_mmgr_ptr(blockp);
/* read the responses */
for (i = 0; i < numentries; i++)
{
site = NULL;
/* skip entries which don't contain valid data */
if (entries[i][0].pfv_code != -(LR_OK))
continue;
/* parse each line */
nextp = entries[i][0].pfv_value;
while ((linep = strsep(&nextp, "\n")) != NULL)
{
/* format is "(site|server):data" */
typep = strsep(&linep, ":");
if (typep == NULL || *typep == '\0')
continue;
/*
** "site" line comes first,
** so save pointer and read next line
*/
if (strcasecmp(typep, "site") == 0)
{
site = linep;
continue;
}
/* for "server" line, create a new element */
if (strcasecmp(typep, "server") == 0)
{
/*
** if we get a "server" line without a
** "site" line, skip it
*/
if (site == NULL)
continue;
if (ph_serverlist_add(serverlist, linep,
site) == -1)
{
save_errno = errno;
ph_mmgr_free(blockp, 1);
errno = save_errno;
return -1;
}
}
}
}
ph_mmgr_free(blockp, 1);
return 0;
}
/*
** ph_free_serverlist() - free memory associated with serverlist.
*/
void
ph_free_serverlist(struct ph_serverlist *serverlist)
{
int i;
for (i = 0; serverlist->sl_list[i].ss_server != NULL; i++)
{
free(serverlist->sl_list[i].ss_server);
free(serverlist->sl_list[i].ss_site);
}
free(serverlist->sl_list);
serverlist->sl_list = NULL;
serverlist->sl_numservers = 0;
}
syntax highlighted by Code2HTML, v. 0.9.1