Mercurial > sm-archive
view src/context.cpp @ 26:c6d5b1658f61
Added tag stable-1-0-9 for changeset a2d60f43590b
author | Carl Byington <carl@five-ten-sg.com> |
---|---|
date | Mon, 06 Feb 2017 12:08:35 -0800 |
parents | 09564d4acd9e |
children |
line wrap: on
line source
/* Copyright (c) 2007 Carl Byington - 510 Software Group, released under the GPL version 3 or any later version at your choice available at http://www.gnu.org/licenses/gpl-3.0.txt */ #include "includes.h" const char *token_envfrom; const char *token_include; const char *token_lbrace; const char *token_rbrace; const char *token_rcptto; const char *token_remove; const 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() { } bool CONFIG::find(const char *needle, string_set &haystack) { string_set::iterator i = haystack.find(needle); if (i != haystack.end()) return true; // found user@domain.tld key const char *x = strchr(needle, '@'); if (x) { x++; i = haystack.find(x); if (i != haystack.end()) return true; // found domain.tld key string userpart(needle, x-needle); i = haystack.find(userpart.c_str()); if (i != haystack.end()) return true; // found user@ key } return false; } const char *CONFIG::find(const char *needle, string_map &haystack) { string_map::iterator i = haystack.find(needle); if (i != haystack.end()) return (*i).second; // found user@domain.tld key const char *x = strchr(needle, '@'); if (x) { x++; i = haystack.find(x); if (i != haystack.end()) return (*i).second; // found domain.tld key string userpart(needle, x-needle); i = haystack.find(userpart.c_str()); 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++) { const char *to = (*i).first; const char *target = (*i).second; if (!target) target = "\"\""; bool rem = find_remove(to); printf(" %s \t %s%s;\n", to, target, (rem) ? " remove" : ""); } printf("};\n"); printf("env_from {\n"); for (string_map::iterator i=env_from.begin(); i!=env_from.end(); i++) { const char *from = (*i).first; const char *target = (*i).second; if (!target) target = "\"\""; 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((void*)*i); } s.clear(); } //////////////////////////////////////////////// // helper to register a string in a string set // const char* register_string(string_set &s, const 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 // const char* register_string(const char *name) { return register_string(all_strings, name); } //////////////////////////////////////////////// // clear all global strings, helper for valgrind checking // void clear_strings() { discard(all_strings); } //////////////////////////////////////////////// // bool tsa(TOKEN &tok, const char *token); bool tsa(TOKEN &tok, const char *token) { const 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) { const char *have = tok.next(); if (!have) break; if (have == token_rbrace) break; const char *target = tok.next(); dc.add_to(have, target); target = tok.next(); if (target == token_remove) { dc.add_remove(have); target = tok.next(); } if (target != token_semi) { tok.token_error(token_semi, target); break; } } 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) { const char *have = tok.next(); if (!have) break; if (have == token_rbrace) break; if (have == token_semi) { // optional separators } else { const char *target = tok.next(); dc.add_from(have, target); } } return tsa(tok, token_semi); } //////////////////////////////////////////////// // parse a config file // bool load_conf(CONFIG &dc, const char *fn) { TOKEN tok(fn, &dc.config_files); while (true) { const 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_remove = register_string("remove"); token_semi = register_string(";"); }