config.c 25.5 KB
Newer Older
Jack Moffitt's avatar
Jack Moffitt committed
1 2 3
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Michael Smith's avatar
Michael Smith committed
4 5
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
6 7

#include "thread/thread.h"
Jack Moffitt's avatar
Jack Moffitt committed
8
#include "config.h"
9 10 11
#include "refbuf.h"
#include "client.h"
#include "logging.h" 
Jack Moffitt's avatar
Jack Moffitt committed
12

13
#define CATMODULE "CONFIG"
Jack Moffitt's avatar
Jack Moffitt committed
14 15 16 17
#define CONFIG_DEFAULT_LOCATION "Earth"
#define CONFIG_DEFAULT_ADMIN "icemaster@localhost"
#define CONFIG_DEFAULT_CLIENT_LIMIT 256
#define CONFIG_DEFAULT_SOURCE_LIMIT 16
18
#define CONFIG_DEFAULT_QUEUE_SIZE_LIMIT (100*1024)
Jack Moffitt's avatar
Jack Moffitt committed
19 20 21
#define CONFIG_DEFAULT_THREADPOOL_SIZE 4
#define CONFIG_DEFAULT_CLIENT_TIMEOUT 30
#define CONFIG_DEFAULT_HEADER_TIMEOUT 15
22
#define CONFIG_DEFAULT_SOURCE_TIMEOUT 10
Jack Moffitt's avatar
Jack Moffitt committed
23
#define CONFIG_DEFAULT_SOURCE_PASSWORD "changeme"
24
#define CONFIG_DEFAULT_RELAY_PASSWORD "changeme"
25
#define CONFIG_DEFAULT_ICE_LOGIN 0
26
#define CONFIG_DEFAULT_FILESERVE 1
Jack Moffitt's avatar
Jack Moffitt committed
27 28 29 30 31
#define CONFIG_DEFAULT_TOUCH_FREQ 5
#define CONFIG_DEFAULT_HOSTNAME "localhost"
#define CONFIG_DEFAULT_PORT 8888
#define CONFIG_DEFAULT_ACCESS_LOG "access.log"
#define CONFIG_DEFAULT_ERROR_LOG "error.log"
32
#define CONFIG_DEFAULT_LOG_LEVEL 4
33 34 35 36
#define CONFIG_DEFAULT_CHROOT 0
#define CONFIG_DEFAULT_CHUID 0
#define CONFIG_DEFAULT_USER NULL
#define CONFIG_DEFAULT_GROUP NULL
37
#define CONFIG_MASTER_UPDATE_INTERVAL 120
38
#define CONFIG_YP_URL_TIMEOUT 10
Jack Moffitt's avatar
Jack Moffitt committed
39

40 41 42
#ifndef _WIN32
#define CONFIG_DEFAULT_BASE_DIR "/usr/local/icecast"
#define CONFIG_DEFAULT_LOG_DIR "/usr/local/icecast/logs"
43
#define CONFIG_DEFAULT_WEBROOT_DIR "/usr/local/icecast/webroot"
44 45 46
#else
#define CONFIG_DEFAULT_BASE_DIR ".\\"
#define CONFIG_DEFAULT_LOG_DIR ".\\logs"
47
#define CONFIG_DEFAULT_WEBROOT_DIR ".\\webroot"
48 49
#endif

50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
ice_config_t _current_configuration;
ice_config_locks _locks;

static void _set_defaults(ice_config_t *c);
static void _parse_root(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_limits(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_directory(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_paths(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_logging(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_security(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node, 
        ice_config_t *c);
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _parse_mount(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);
static void _add_server(xmlDocPtr doc, xmlNodePtr node, ice_config_t *c);

static void create_locks() {
    thread_mutex_create(&_locks.relay_lock);
    thread_mutex_create(&_locks.mounts_lock);
    thread_mutex_create(&_locks.config_lock);
}

static void release_locks() {
    thread_mutex_destroy(&_locks.relay_lock);
    thread_mutex_destroy(&_locks.mounts_lock);
    thread_mutex_destroy(&_locks.config_lock);
}

void config_initialize(void) {
    create_locks();
}

void config_shutdown(void) {
    config_get_config();
    config_clear(&_current_configuration);
    config_release_config();
    release_locks();
}

void config_init_configuration(ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
90
{
91 92
	memset(configuration, 0, sizeof(ice_config_t));
	_set_defaults(configuration);
Jack Moffitt's avatar
Jack Moffitt committed
93 94
}

95
void config_clear(ice_config_t *c)
Jack Moffitt's avatar
Jack Moffitt committed
96
{
97
	ice_config_dir_t *dirnode, *nextdirnode;
98
    relay_server *relay, *nextrelay;
99
    mount_proxy *mount, *nextmount;
Jack Moffitt's avatar
Jack Moffitt committed
100

101 102
    if (c->config_filename)
        free(c->config_filename);
103 104 105 106 107 108 109

	if (c->location && c->location != CONFIG_DEFAULT_LOCATION) 
        xmlFree(c->location);
	if (c->admin && c->admin != CONFIG_DEFAULT_ADMIN) 
        xmlFree(c->admin);
	if (c->source_password && c->source_password != CONFIG_DEFAULT_SOURCE_PASSWORD)
        xmlFree(c->source_password);
110 111
	if (c->relay_password && c->relay_password != CONFIG_DEFAULT_SOURCE_PASSWORD)
        xmlFree(c->relay_password);
112 113 114 115
	if (c->admin_username)
        xmlFree(c->admin_username);
	if (c->admin_password)
        xmlFree(c->admin_password);
116 117 118 119 120 121
	if (c->hostname && c->hostname != CONFIG_DEFAULT_HOSTNAME) 
        xmlFree(c->hostname);
	if (c->base_dir && c->base_dir != CONFIG_DEFAULT_BASE_DIR) 
        xmlFree(c->base_dir);
	if (c->log_dir && c->log_dir != CONFIG_DEFAULT_LOG_DIR) 
        xmlFree(c->log_dir);
Michael Smith's avatar
Michael Smith committed
122
    if (c->webroot_dir && c->webroot_dir != CONFIG_DEFAULT_WEBROOT_DIR)
123
        xmlFree(c->webroot_dir);
124 125 126 127 128
	if (c->access_log && c->access_log != CONFIG_DEFAULT_ACCESS_LOG) 
        xmlFree(c->access_log);
	if (c->error_log && c->error_log != CONFIG_DEFAULT_ERROR_LOG) 
        xmlFree(c->error_log);
    if (c->bind_address) xmlFree(c->bind_address);
129 130
    if (c->master_server) xmlFree(c->master_server);
    if (c->master_password) xmlFree(c->master_password);
131 132
    if (c->user) xmlFree(c->user);
    if (c->group) xmlFree(c->group);
133 134 135

    thread_mutex_lock(&(_locks.relay_lock));
    relay = c->relay;
136 137 138 139
    while(relay) {
        nextrelay = relay->next;
        xmlFree(relay->server);
        xmlFree(relay->mount);
140 141
        if(relay->localmount)
            xmlFree(relay->localmount);
142 143 144
        free(relay);
        relay = nextrelay;
    }
145 146 147 148
    thread_mutex_unlock(&(_locks.relay_lock));

    thread_mutex_lock(&(_locks.mounts_lock));
    mount = c->mounts;
149 150 151 152 153 154 155 156 157 158
    while(mount) {
        nextmount = mount->next;
        xmlFree(mount->mountname);
        xmlFree(mount->username);
        xmlFree(mount->password);
        xmlFree(mount->dumpfile);
        xmlFree(mount->fallback_mount);
        free(mount);
        mount = nextmount;
    }
159 160 161
    thread_mutex_unlock(&(_locks.mounts_lock));

    dirnode = c->dir_list;
162 163
    while(dirnode) {
        nextdirnode = dirnode->next;
164
        xmlFree(dirnode->host);
165 166 167
        free(dirnode);
        dirnode = nextdirnode;
    }
Jack Moffitt's avatar
Jack Moffitt committed
168

169
    memset(c, 0, sizeof(ice_config_t));
Jack Moffitt's avatar
Jack Moffitt committed
170 171
}

172 173 174 175 176 177 178
int config_initial_parse_file(const char *filename)
{
    /* Since we're already pointing at it, we don't need to copy it in place */
    return config_parse_file(filename, &_current_configuration);
}

int config_parse_file(const char *filename, ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
179 180 181 182 183 184
{
	xmlDocPtr doc;
	xmlNodePtr node;

	if (filename == NULL || strcmp(filename, "") == 0) return CONFIG_EINSANE;
	
Michael Smith's avatar
Michael Smith committed
185
    xmlInitParser();
186
	doc = xmlParseFile(filename);
Jack Moffitt's avatar
Jack Moffitt committed
187
	if (doc == NULL) {
188
		return CONFIG_EPARSE;
Jack Moffitt's avatar
Jack Moffitt committed
189 190 191 192 193
	}

	node = xmlDocGetRootElement(doc);
	if (node == NULL) {
		xmlFreeDoc(doc);
Michael Smith's avatar
Michael Smith committed
194
        xmlCleanupParser();
Jack Moffitt's avatar
Jack Moffitt committed
195 196 197 198 199
		return CONFIG_ENOROOT;
	}

	if (strcmp(node->name, "icecast") != 0) {
		xmlFreeDoc(doc);
Michael Smith's avatar
Michael Smith committed
200
        xmlCleanupParser();
Jack Moffitt's avatar
Jack Moffitt committed
201 202 203
		return CONFIG_EBADROOT;
	}

204 205 206 207 208
    config_init_configuration(configuration);

	configuration->config_filename = (char *)strdup(filename);

	_parse_root(doc, node->xmlChildrenNode, configuration);
Jack Moffitt's avatar
Jack Moffitt committed
209 210

	xmlFreeDoc(doc);
Michael Smith's avatar
Michael Smith committed
211
    xmlCleanupParser();
Jack Moffitt's avatar
Jack Moffitt committed
212 213 214 215 216 217 218 219 220

	return 0;
}

int config_parse_cmdline(int arg, char **argv)
{
	return 0;
}

221
ice_config_locks *config_locks(void)
Jack Moffitt's avatar
Jack Moffitt committed
222
{
223 224 225 226 227 228
    return &_locks;
}

void config_release_config(void)
{
    thread_mutex_unlock(&(_locks.config_lock));
Jack Moffitt's avatar
Jack Moffitt committed
229 230 231 232
}

ice_config_t *config_get_config(void)
{
233 234 235 236 237 238 239 240 241 242 243 244
    thread_mutex_lock(&(_locks.config_lock));
	return &_current_configuration;
}

/* MUST be called with the lock held! */
void config_set_config(ice_config_t *config) {
    memcpy(&_current_configuration, config, sizeof(ice_config_t));
}

ice_config_t *config_get_config_unlocked(void)
{
	return &_current_configuration;
Jack Moffitt's avatar
Jack Moffitt committed
245 246
}

247
static void _set_defaults(ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
248
{
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
	configuration->location = CONFIG_DEFAULT_LOCATION;
	configuration->admin = CONFIG_DEFAULT_ADMIN;
	configuration->client_limit = CONFIG_DEFAULT_CLIENT_LIMIT;
	configuration->source_limit = CONFIG_DEFAULT_SOURCE_LIMIT;
	configuration->queue_size_limit = CONFIG_DEFAULT_QUEUE_SIZE_LIMIT;
	configuration->threadpool_size = CONFIG_DEFAULT_THREADPOOL_SIZE;
	configuration->client_timeout = CONFIG_DEFAULT_CLIENT_TIMEOUT;
	configuration->header_timeout = CONFIG_DEFAULT_HEADER_TIMEOUT;
	configuration->source_timeout = CONFIG_DEFAULT_SOURCE_TIMEOUT;
	configuration->source_password = CONFIG_DEFAULT_SOURCE_PASSWORD;
	configuration->relay_password = CONFIG_DEFAULT_RELAY_PASSWORD;
	configuration->ice_login = CONFIG_DEFAULT_ICE_LOGIN;
	configuration->fileserve = CONFIG_DEFAULT_FILESERVE;
	configuration->touch_interval = CONFIG_DEFAULT_TOUCH_FREQ;
	configuration->dir_list = NULL;
	configuration->hostname = CONFIG_DEFAULT_HOSTNAME;
	configuration->port = CONFIG_DEFAULT_PORT;
	configuration->bind_address = NULL;
	configuration->master_server = NULL;
	configuration->master_server_port = CONFIG_DEFAULT_PORT;
    configuration->master_update_interval = CONFIG_MASTER_UPDATE_INTERVAL;
	configuration->master_password = NULL;
	configuration->base_dir = CONFIG_DEFAULT_BASE_DIR;
	configuration->log_dir = CONFIG_DEFAULT_LOG_DIR;
    configuration->webroot_dir = CONFIG_DEFAULT_WEBROOT_DIR;
	configuration->access_log = CONFIG_DEFAULT_ACCESS_LOG;
	configuration->error_log = CONFIG_DEFAULT_ERROR_LOG;
	configuration->loglevel = CONFIG_DEFAULT_LOG_LEVEL;
    configuration->chroot = CONFIG_DEFAULT_CHROOT;
    configuration->chuid = CONFIG_DEFAULT_CHUID;
    configuration->user = CONFIG_DEFAULT_USER;
    configuration->group = CONFIG_DEFAULT_GROUP;
    configuration->num_yp_directories = 0;
Jack Moffitt's avatar
Jack Moffitt committed
282 283
}

284 285
static void _parse_root(xmlDocPtr doc, xmlNodePtr node, 
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
286 287 288 289 290 291 292 293
{
	char *tmp;

	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "location") == 0) {
294 295
			if (configuration->location && configuration->location != CONFIG_DEFAULT_LOCATION) xmlFree(configuration->location);
			configuration->location = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Jack Moffitt's avatar
Jack Moffitt committed
296
		} else if (strcmp(node->name, "admin") == 0) {
297 298
			if (configuration->admin && configuration->admin != CONFIG_DEFAULT_ADMIN) xmlFree(configuration->admin);
			configuration->admin = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
299
		} else if(strcmp(node->name, "authentication") == 0) {
300
			_parse_authentication(doc, node->xmlChildrenNode, configuration);
301 302
        } else if (strcmp(node->name, "source-password") == 0) {
            /* TODO: This is the backwards-compatibility location */
303 304 305 306 307 308
            char *mount, *pass;
            if ((mount = (char *)xmlGetProp(node, "mount")) != NULL) {
                pass = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
                /* FIXME: This is a placeholder for per-mount passwords */
            }
            else {
309 310
			    if (configuration->source_password && configuration->source_password != CONFIG_DEFAULT_SOURCE_PASSWORD) xmlFree(configuration->source_password);
			    configuration->source_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
311
            }
312
        } else if (strcmp(node->name, "relay-password") == 0) {
313
            /* TODO: This is the backwards-compatibility location */
314 315
			if (configuration->relay_password && configuration->relay_password != CONFIG_DEFAULT_RELAY_PASSWORD) xmlFree(configuration->relay_password);
			configuration->relay_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
316 317
		} else if (strcmp(node->name, "icelogin") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
318
			configuration->ice_login = atoi(tmp);
319
			if (tmp) xmlFree(tmp);
320 321
		} else if (strcmp(node->name, "fileserve") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
322
			configuration->fileserve = atoi(tmp);
323
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
324
		} else if (strcmp(node->name, "hostname") == 0) {
325 326
			if (configuration->hostname && configuration->hostname != CONFIG_DEFAULT_HOSTNAME) xmlFree(configuration->hostname);
			configuration->hostname = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Jack Moffitt's avatar
Jack Moffitt committed
327 328
		} else if (strcmp(node->name, "port") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
329
			configuration->port = atoi(tmp);
330
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
331
		} else if (strcmp(node->name, "bind-address") == 0) {
332 333
			if (configuration->bind_address) xmlFree(configuration->bind_address);
			configuration->bind_address = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
334
		} else if (strcmp(node->name, "master-server") == 0) {
335 336
			if (configuration->master_server) xmlFree(configuration->master_server);
			configuration->master_server = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
337
		} else if (strcmp(node->name, "master-password") == 0) {
338 339
			if (configuration->master_password) xmlFree(configuration->master_password);
			configuration->master_password = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
340 341
		} else if (strcmp(node->name, "master-server-port") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
342
			configuration->master_server_port = atoi(tmp);
343 344
        } else if (strcmp(node->name, "master-update-interval") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
345
            configuration->master_update_interval = atoi(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
346
		} else if (strcmp(node->name, "limits") == 0) {
347
			_parse_limits(doc, node->xmlChildrenNode, configuration);
348
		} else if (strcmp(node->name, "relay") == 0) {
349
			_parse_relay(doc, node->xmlChildrenNode, configuration);
350
		} else if (strcmp(node->name, "mount") == 0) {
351
			_parse_mount(doc, node->xmlChildrenNode, configuration);
Jack Moffitt's avatar
Jack Moffitt committed
352
		} else if (strcmp(node->name, "directory") == 0) {
353
			_parse_directory(doc, node->xmlChildrenNode, configuration);
Jack Moffitt's avatar
Jack Moffitt committed
354
		} else if (strcmp(node->name, "paths") == 0) {
355
			_parse_paths(doc, node->xmlChildrenNode, configuration);
Jack Moffitt's avatar
Jack Moffitt committed
356
		} else if (strcmp(node->name, "logging") == 0) {
357
			_parse_logging(doc, node->xmlChildrenNode, configuration);
358
        } else if (strcmp(node->name, "security") == 0) {
359
            _parse_security(doc, node->xmlChildrenNode, configuration);
Jack Moffitt's avatar
Jack Moffitt committed
360 361 362 363
		}
	} while ((node = node->next));
}

364 365
static void _parse_limits(xmlDocPtr doc, xmlNodePtr node, 
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
366 367 368 369 370 371 372 373 374
{
	char *tmp;

	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "clients") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
375
			configuration->client_limit = atoi(tmp);
376
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
377 378
		} else if (strcmp(node->name, "sources") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
379
			configuration->source_limit = atoi(tmp);
380
			if (tmp) xmlFree(tmp);
381 382
		} else if (strcmp(node->name, "queue-size") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
383
			configuration->queue_size_limit = atoi(tmp);
384
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
385 386
		} else if (strcmp(node->name, "threadpool") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
387
			configuration->threadpool_size = atoi(tmp);
388
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
389 390
		} else if (strcmp(node->name, "client-timeout") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
391
			configuration->client_timeout = atoi(tmp);
392
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
393 394
		} else if (strcmp(node->name, "header-timeout") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
395
			configuration->header_timeout = atoi(tmp);
396
			if (tmp) xmlFree(tmp);
397 398
		} else if (strcmp(node->name, "source-timeout") == 0) {
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
399
			configuration->source_timeout = atoi(tmp);
400
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
401 402 403 404
		}
	} while ((node = node->next));
}

405 406
static void _parse_mount(xmlDocPtr doc, xmlNodePtr node, 
        ice_config_t *configuration)
407 408 409
{
    char *tmp;
    mount_proxy *mount = calloc(1, sizeof(mount_proxy));
410
    mount_proxy *current = configuration->mounts;
411 412 413 414 415 416 417 418 419 420
    mount_proxy *last=NULL;
    
    while(current) {
        last = current;
        current = current->next;
    }

    if(last)
        last->next = mount;
    else
421
        configuration->mounts = mount;
422

423 424
    mount->max_listeners = -1;

425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "mount-name") == 0) {
            mount->mountname = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "username") == 0) {
            mount->username = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "password") == 0) {
            mount->password = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "dump-file") == 0) {
            mount->dumpfile = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "fallback-mount") == 0) {
            mount->fallback_mount = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "max-listeners") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            mount->max_listeners = atoi(tmp);
            if(tmp) xmlFree(tmp);
        }
	} while ((node = node->next));
}

457 458
static void _parse_relay(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
459 460 461
{
    char *tmp;
    relay_server *relay = calloc(1, sizeof(relay_server));
462
    relay_server *current = configuration->relay;
463 464 465 466 467 468 469 470 471 472
    relay_server *last=NULL;
    
    while(current) {
        last = current;
        current = current->next;
    }

    if(last)
        last->next = relay;
    else
473
        configuration->relay = relay;
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491

	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "server") == 0) {
			relay->server = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
        else if (strcmp(node->name, "port") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            relay->port = atoi(tmp);
            if(tmp) xmlFree(tmp);
        }
        else if (strcmp(node->name, "mount") == 0) {
			relay->mount = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
492 493 494 495
        else if (strcmp(node->name, "local-mount") == 0) {
			relay->localmount = (char *)xmlNodeListGetString(
                    doc, node->xmlChildrenNode, 1);
        }
496 497 498 499 500
        else if (strcmp(node->name, "relay-shoutcast-metadata") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            relay->mp3metadata = atoi(tmp);
            if(tmp) xmlFree(tmp);
        }
501 502 503
	} while ((node = node->next));
}

504 505
static void _parse_authentication(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
506 507 508 509 510 511 512 513 514 515 516 517
{
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "source-password") == 0) {
            char *mount, *pass;
            if ((mount = (char *)xmlGetProp(node, "mount")) != NULL) {
                pass = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
                /* FIXME: This is a placeholder for per-mount passwords */
            }
            else {
518 519
			    if (configuration->source_password && 
                        configuration->source_password != 
520
                        CONFIG_DEFAULT_SOURCE_PASSWORD) 
521 522
                    xmlFree(configuration->source_password);
			    configuration->source_password = 
523 524 525
                    (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            }
        } else if (strcmp(node->name, "relay-password") == 0) {
526 527
			if (configuration->relay_password && 
                    configuration->relay_password != 
528
                    CONFIG_DEFAULT_RELAY_PASSWORD) 
529 530
                xmlFree(configuration->relay_password);
			configuration->relay_password = 
531 532
                (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
		} else if (strcmp(node->name, "admin-password") == 0) {
533 534 535
            if(configuration->admin_password)
                xmlFree(configuration->admin_password);
            configuration->admin_password =
536 537
                (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
		} else if (strcmp(node->name, "admin-user") == 0) {
538 539 540
            if(configuration->admin_username)
                xmlFree(configuration->admin_username);
            configuration->admin_username =
541 542 543 544 545
                (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
        }
	} while ((node = node->next));
}

546 547
static void _parse_directory(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
548 549 550
{
	char *tmp;

551
	if (configuration->num_yp_directories >= MAX_YP_DIRECTORIES) {
552 553 554
		ERROR0("Maximum number of yp directories exceeded!");
		return;
	}
Jack Moffitt's avatar
Jack Moffitt committed
555 556 557 558
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

559
		if (strcmp(node->name, "yp-url") == 0) {
560 561 562
			if (configuration->yp_url[configuration->num_yp_directories]) 
                xmlFree(configuration->yp_url[configuration->num_yp_directories]);
			configuration->yp_url[configuration->num_yp_directories] = 
563
                (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
564 565
        } else if (strcmp(node->name, "yp-url-timeout") == 0) {
            tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
566
            configuration->yp_url_timeout[configuration->num_yp_directories] = 
567
                atoi(tmp);
568
		} else if (strcmp(node->name, "server") == 0) {
569
			_add_server(doc, node->xmlChildrenNode, configuration);
570
		} else if (strcmp(node->name, "touch-interval") == 0) {
Jack Moffitt's avatar
Jack Moffitt committed
571
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
572
			configuration->touch_interval = atoi(tmp);
573
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
574 575
		}
	} while ((node = node->next));
576
	configuration->num_yp_directories++;
Jack Moffitt's avatar
Jack Moffitt committed
577 578
}

579 580
static void _parse_paths(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
581 582 583 584 585 586
{
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "basedir") == 0) {
587 588
			if (configuration->base_dir && configuration->base_dir != CONFIG_DEFAULT_BASE_DIR) xmlFree(configuration->base_dir);
			configuration->base_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Jack Moffitt's avatar
Jack Moffitt committed
589
		} else if (strcmp(node->name, "logdir") == 0) {
590 591
			if (configuration->log_dir && configuration->log_dir != CONFIG_DEFAULT_LOG_DIR) xmlFree(configuration->log_dir);
			configuration->log_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
592
		} else if (strcmp(node->name, "webroot") == 0) {
593 594 595 596
			if (configuration->webroot_dir && configuration->webroot_dir != CONFIG_DEFAULT_WEBROOT_DIR) xmlFree(configuration->webroot_dir);
			configuration->webroot_dir = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
            if(configuration->webroot_dir[strlen(configuration->webroot_dir)-1] == '/')
                configuration->webroot_dir[strlen(configuration->webroot_dir)-1] = 0;
597

Jack Moffitt's avatar
Jack Moffitt committed
598 599 600 601
		}
	} while ((node = node->next));
}

602 603
static void _parse_logging(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
604 605 606 607 608 609
{
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "accesslog") == 0) {
610 611
			if (configuration->access_log && configuration->access_log != CONFIG_DEFAULT_ACCESS_LOG) xmlFree(configuration->access_log);
			configuration->access_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
Jack Moffitt's avatar
Jack Moffitt committed
612
		} else if (strcmp(node->name, "errorlog") == 0) {
613 614
			if (configuration->error_log && configuration->error_log != CONFIG_DEFAULT_ERROR_LOG) xmlFree(configuration->error_log);
			configuration->error_log = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
615 616
		} else if (strcmp(node->name, "loglevel") == 0) {
           char *tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
617
           configuration->loglevel = atoi(tmp);
618
           if (tmp) xmlFree(tmp);
619
        }
Jack Moffitt's avatar
Jack Moffitt committed
620 621 622
	} while ((node = node->next));
}

623 624
static void _parse_security(xmlDocPtr doc, xmlNodePtr node,
        ice_config_t *configuration)
625 626 627 628 629 630 631 632 633 634
{
   char *tmp;
   xmlNodePtr oldnode;

   do {
       if (node == NULL) break;
       if (xmlIsBlankNode(node)) continue;

       if (strcmp(node->name, "chroot") == 0) {
           tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
635
           configuration->chroot = atoi(tmp);
636
           if (tmp) xmlFree(tmp);
637
       } else if (strcmp(node->name, "changeowner") == 0) {
638
           configuration->chuid = 1;
639 640 641 642 643 644
           oldnode = node;
           node = node->xmlChildrenNode;
           do {
               if(node == NULL) break;
               if(xmlIsBlankNode(node)) continue;
               if(strcmp(node->name, "user") == 0) {
645 646
                   if(configuration->user) xmlFree(configuration->user);
                   configuration->user = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
647
               } else if(strcmp(node->name, "group") == 0) {
648 649
                   if(configuration->group) xmlFree(configuration->group);
                   configuration->group = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
650 651 652 653 654 655 656
               }
           } while((node = node->next));
           node = oldnode;
       }
   } while ((node = node->next));
}

657 658
static void _add_server(xmlDocPtr doc, xmlNodePtr node, 
        ice_config_t *configuration)
Jack Moffitt's avatar
Jack Moffitt committed
659 660 661 662 663 664
{
	ice_config_dir_t *dirnode, *server;
	int addnode;
	char *tmp;

	server = (ice_config_dir_t *)malloc(sizeof(ice_config_dir_t));
665
	server->touch_interval = configuration->touch_interval;
Jack Moffitt's avatar
Jack Moffitt committed
666 667 668 669 670 671 672 673
	server->host = NULL;
	addnode = 0;
	
	do {
		if (node == NULL) break;
		if (xmlIsBlankNode(node)) continue;

		if (strcmp(node->name, "host") == 0) {
674 675
			server->host = (char *)xmlNodeListGetString(doc, 
                    node->xmlChildrenNode, 1);
Jack Moffitt's avatar
Jack Moffitt committed
676
			addnode = 1;
677
		} else if (strcmp(node->name, "touch-interval") == 0) {
Jack Moffitt's avatar
Jack Moffitt committed
678
			tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
679
			server->touch_interval = atoi(tmp);
680
			if (tmp) xmlFree(tmp);
Jack Moffitt's avatar
Jack Moffitt committed
681 682 683 684 685
		}
		server->next = NULL;
	} while ((node = node->next));

	if (addnode) {
686
		dirnode = configuration->dir_list;
Jack Moffitt's avatar
Jack Moffitt committed
687
		if (dirnode == NULL) {
688
			configuration->dir_list = server;
Jack Moffitt's avatar
Jack Moffitt committed
689 690 691 692 693 694 695 696 697 698 699 700 701
		} else {
			while (dirnode->next) dirnode = dirnode->next;
			
			dirnode->next = server;
		}
		
		server = NULL;
		addnode = 0;
	}
	
}