view sip-manual-out/readconf.c @ 171:4f1f3f799295

doc/Codec-library-depend: article written
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 21 Nov 2022 01:01:39 -0800
parents d74b545a3c2a
children
line wrap: on
line source

/*
 * In this module we implement the reading of destination configuration
 * for sip-manual-out.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

struct in_addr sip_bind_ip, sip_dest_ip;
unsigned sip_bind_port, sip_dest_port = 5060;
char sip_dest_domain[64];

struct parse_state {
	char *filename;
	int lineno;
	int set_mask;
};

static void
handle_ip(st, kw, var, arg)
	struct parse_state *st;
	char *kw, *arg;
	struct in_addr *var;
{
	var->s_addr = inet_addr(arg);
	if (var->s_addr == INADDR_NONE) {
		fprintf(stderr,
			"%s line %d: invalid IP address argument \"%s\"\n",
			st->filename, st->lineno, arg);
		exit(1);
	}
}

static void
handle_num(st, kw, var, arg)
	struct parse_state *st;
	char *kw, *arg;
	unsigned *var;
{
	char *endp;

	*var = strtoul(arg, &endp, 10);
	if (*endp) {
		fprintf(stderr, "%s line %d: invalid numeric argument \"%s\"\n",
			st->filename, st->lineno, arg);
		exit(1);
	}
}

static void
handle_str(st, kw, var, arg)
	struct parse_state *st;
	char *kw, *arg, *var;
{
	strcpy(var, arg);
}

static void
process_line(st, line)
	struct parse_state *st;
	char *line;
{
	char *cp, *np, *arg;
	void (*handler)(), *var;
	int set_id;

	if (!index(line, '\n')) {
		fprintf(stderr, "%s line %d: too long or missing newline\n",
			st->filename, st->lineno);
		exit(1);
	}
	for (cp = line; isspace(*cp); cp++)
		;
	if (*cp == '\0' || *cp == '#')
		return;
	for (np = cp; *cp && !isspace(*cp); cp++)
		;
	if (*cp)
		*cp++ = '\0';
	if (!strcmp(np, "bind-ip")) {
		handler = handle_ip;
		var = &sip_bind_ip;
		set_id = 1;
	} else if (!strcmp(np, "bind-port")) {
		handler = handle_num;
		var = &sip_bind_port;
		set_id = 2;
	} else if (!strcmp(np, "dest-ip")) {
		handler = handle_ip;
		var = &sip_dest_ip;
		set_id = 4;
	} else if (!strcmp(np, "dest-port")) {
		handler = handle_num;
		var = &sip_dest_port;
		set_id = 0;
	} else if (!strcmp(np, "dest-domain")) {
		handler = handle_str;
		var = sip_dest_domain;
		set_id = 8;
	} else {
		fprintf(stderr, "%s line %d: non-understood keyword \"%s\"\n",
			st->filename, st->lineno, np);
		exit(1);
	}
	if (st->set_mask & set_id) {
		fprintf(stderr, "%s line %d: duplicate %s setting\n",
			st->filename, st->lineno, np);
		exit(1);
	}
	while (isspace(*cp))
		cp++;
	if (*cp == '\0' || *cp == '#') {
inv_syntax:	fprintf(stderr,
			"%s line %d: %s setting requires one argument\n",
			st->filename, st->lineno, np);
		exit(1);
	}
	for (arg = cp; *cp && !isspace(*cp); cp++)
		;
	if (*cp)
		*cp++ = '\0';
	while (isspace(*cp))
		cp++;
	if (*cp != '\0' && *cp != '#')
		goto inv_syntax;
	handler(st, np, var, arg);
	st->set_mask |= set_id;
}

read_config_file(filename)
	char *filename;
{
	FILE *inf;
	struct parse_state pst;
	char linebuf[256];

	inf = fopen(filename, "r");
	if (!inf) {
		perror(filename);
		exit(1);
	}
	pst.set_mask = 0;
	pst.filename = filename;
	for (pst.lineno = 1; fgets(linebuf, sizeof linebuf, inf); pst.lineno++)
		process_line(&pst, linebuf);
	fclose(inf);
	if (pst.set_mask != 15) {
		fprintf(stderr, "error: %s did not set all required settings\n",
			filename);
		exit(1);
	}
}