view src/context.cpp @ 8:ed73e6361570 stable-1-0

initial version
author carl
date Fri, 10 Mar 2006 12:55:07 -0800
parents 01268466f0dc
children 61a4e8773e2e
line wrap: on
line source

/*

Copyright (c) 2004 Carl Byington - 510 Software Group, released under
the GPL version 2 or any later version at your choice available at
http://www.fsf.org/licenses/gpl.txt

*/

#include "includes.h"

// needed for socket io
#include <unistd.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/un.h>

static char* context_version="$Id$";

char *token_envfrom;
char *token_include;
char *token_lbrace;
char *token_rbrace;
char *token_rcptto;
char *token_semi;

string_set	all_strings;	// owns all the strings, only modified by the config loader thread
const int maxlen = 1000;	// used for snprintf buffers

CONFIG::CONFIG() {
	reference_count    = 0;
	generation		   = 0;
	load_time		   = 0;
}


CONFIG::~CONFIG() {
}


char *CONFIG::find(char *needle, string_map &haystack) {
	string_map::iterator i = haystack.find(needle);
	if (i != haystack.end()) return (*i).second;	  // found user@domain.tld key
	char *x = strchr(needle, '@');
	if (x) {
		x++;
		i = haystack.find(x);
		if (i != haystack.end()) return (*i).second;  // found domain.tld key
		char y = *x;
		*x = '\0';
		i = haystack.find(needle);
		*x = y;
		if (i != haystack.end()) return (*i).second;  // found user@ key
	}
	return NULL;
}


void CONFIG::dump() {
	printf("rcpt_to {\n");
	for (string_map::iterator i=rcpt_to.begin(); i!=rcpt_to.end(); i++) {
		char	 *to = (*i).first;
		char *target = (*i).second;
		printf("    %s \t %s\n", to, target);
	}
	printf("};\n");
	printf("env_from {\n");
	for (string_map::iterator i=env_from.begin(); i!=env_from.end(); i++) {
		char   *from = (*i).first;
		char *target = (*i).second;
		printf("    %s \t %s\n", from, target);
	}
	printf("};\n");
}


////////////////////////////////////////////////
// helper to discard the strings held by a string_set
//
void discard(string_set &s) {
	for (string_set::iterator i=s.begin(); i!=s.end(); i++) {
		free(*i);
	}
	s.clear();
}


////////////////////////////////////////////////
// helper to register a string in a string set
//
char* register_string(string_set &s, char *name) {
	string_set::iterator i = s.find(name);
	if (i != s.end()) return *i;
	char *x = strdup(name);
	s.insert(x);
	return x;
}


////////////////////////////////////////////////
// register a global string
//
char* register_string(char *name) {
	return register_string(all_strings, name);
}


////////////////////////////////////////////////
//
bool tsa(TOKEN &tok, char *token);
bool tsa(TOKEN &tok, char *token) {
	char *have = tok.next();
	if (have == token) return true;
	tok.token_error(token, have);
	return false;
}


////////////////////////////////////////////////
//
bool parse_rcpt_to(TOKEN &tok, CONFIG &dc);
bool parse_rcpt_to(TOKEN &tok, CONFIG &dc) {
	if (!tsa(tok, token_lbrace)) return false;
	while (true) {
		char *have = tok.next();
		if (!have) break;
		if (have == token_rbrace) break;
		if (have == token_semi) {
			// optional separators
		}
		else {
			char *target = tok.next();
			dc.add_to(have, target);
		}
	}
	return tsa(tok, token_semi);
}


////////////////////////////////////////////////
//
bool parse_env_from(TOKEN &tok, CONFIG &dc);
bool parse_env_from(TOKEN &tok, CONFIG &dc) {
	if (!tsa(tok, token_lbrace)) return false;
	while (true) {
		char *have = tok.next();
		if (!have) break;
		if (have == token_rbrace) break;
		if (have == token_semi) {
			// optional separators
		}
		else {
			char *target = tok.next();
			dc.add_from(have, target);
		}
	}
	return tsa(tok, token_semi);
}


////////////////////////////////////////////////
// parse a config file
//
bool load_conf(CONFIG &dc, char *fn) {
	TOKEN tok(fn, &dc.config_files);
	while (true) {
		char *have = tok.next();
		if (!have) break;
		if (have == token_envfrom) {
			if (!parse_env_from(tok, dc)) {
				tok.token_error("load_conf() failed to parse env_from");
				return false;
			}
		}
		else if (have == token_rcptto) {
			if (!parse_rcpt_to(tok, dc)) {
				tok.token_error("load_conf() failed to parse rcpt_to");
				return false;
			}
		}
		else {
			tok.token_error("env_from/rcpt_to", have);
			return false;
		}
	}
	return true;
}


////////////////////////////////////////////////
// init the tokens
//
void token_init() {
	token_envfrom	 = register_string("env_from");
	token_include	 = register_string("include");
	token_lbrace	 = register_string("{");
	token_rbrace	 = register_string("}");
	token_rcptto	 = register_string("rcpt_to");
	token_semi		 = register_string(";");
}