#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <errno.h>
#include "replica.h"
void
free_replica(struct replica *list, int count)
{
int i;
for (i = 0; i < count; i++) {
if (list[i].host)
free(list[i].host);
if (list[i].path)
free(list[i].path);
}
free(list);
}
struct replica *
parse_replica(char *special, int *count)
{
struct replica *list = NULL;
char *root, *special2;
char *proot, *x, *y;
int scount, v6addr, i;
int found_colon = 0;
*count = 0;
scount = 0;
v6addr = 0;
root = special2 = strdup(special);
proot = root;
while (root) {
switch (*root) {
case '[':
if ((root != special2) && (*(root -1) != ',')) {
root++;
break;
}
y = strchr(root, ']');
if (!y) {
root++;
break;
}
if ((*(y + 1) != ',') && (*(y + 1) != ':')) {
root = y + 1;
break;
}
proot = root + 1;
root = y + 1;
v6addr = 1;
if ((list = realloc(list, (*count + 1) *
sizeof (struct replica))) == NULL)
goto bad;
bzero(&list[(*count)++], sizeof (struct replica));
*y = '\0';
list[*count-1].host = strdup(proot);
if (!list[*count-1].host)
goto bad;
break;
case ':':
*root = '\0';
x = root + 1;
if (((y = strchr(x, ',')) != NULL) &&
(strchr((y + 1), ':'))) {
root = y + 1;
*y = '\0';
} else {
found_colon = 1;
root = NULL;
}
if (v6addr == 1)
v6addr = 0;
else {
if ((list = realloc(list, (*count + 1) *
sizeof (struct replica))) == NULL)
goto bad;
bzero(&list[(*count)++],
sizeof (struct replica));
list[*count-1].host = strdup(proot);
if (!list[*count-1].host)
goto bad;
proot = root;
}
for (i = scount; i < *count; i++) {
list[i].path = strdup(x);
if (!list[i].path)
goto bad;
}
scount = i;
proot = root;
if (y)
*y = ',';
break;
case ',':
if (v6addr == 1) {
v6addr = 0;
proot = ++root;
} else {
*root = '\0';
root++;
if ((list = realloc(list, (*count + 1) *
sizeof (struct replica))) == NULL)
goto bad;
bzero(&list[(*count)++],
sizeof (struct replica));
list[*count-1].host = strdup(proot);
if (!list[*count-1].host)
goto bad;
proot = root;
*(root - 1) = ',';
}
break;
default:
if (*root == '\0')
root = NULL;
else
root++;
}
}
if (found_colon) {
free(special2);
return (list);
}
bad:
if (list)
free_replica(list, *count);
if (!found_colon)
*count = -1;
free(special2);
return (NULL);
}