2011-11-14 15:57:52 +01:00
|
|
|
/*
|
|
|
|
* piler.c, SJ
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <strings.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
2015-05-09 14:31:20 +02:00
|
|
|
#include <sys/mman.h>
|
2013-04-02 16:35:32 +02:00
|
|
|
#include <netdb.h>
|
2011-11-14 15:57:52 +01:00
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/wait.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <pwd.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <syslog.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <unistd.h>
|
2016-10-26 21:26:20 +02:00
|
|
|
#include <dirent.h>
|
2011-11-14 15:57:52 +01:00
|
|
|
#include <locale.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <piler.h>
|
|
|
|
|
2016-10-26 21:26:20 +02:00
|
|
|
#define PROGNAME "piler"
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
extern char *optarg;
|
|
|
|
extern int optind;
|
|
|
|
|
|
|
|
int sd;
|
2012-01-07 00:00:36 +01:00
|
|
|
int quit = 0;
|
|
|
|
int received_sighup = 0;
|
2011-11-14 15:57:52 +01:00
|
|
|
char *configfile = CONFIG_FILE;
|
|
|
|
struct __config cfg;
|
|
|
|
struct __data data;
|
|
|
|
struct passwd *pwd;
|
|
|
|
|
2012-01-07 00:00:36 +01:00
|
|
|
struct child children[MAXCHILDREN];
|
|
|
|
|
|
|
|
|
|
|
|
static void takesig(int sig);
|
|
|
|
static void child_sighup_handler(int sig);
|
|
|
|
static void child_main(struct child *ptr);
|
|
|
|
static pid_t child_make(struct child *ptr);
|
|
|
|
int search_slot_by_pid(pid_t pid);
|
|
|
|
void kill_children(int sig);
|
2012-10-29 10:22:31 +01:00
|
|
|
void p_clean_exit();
|
2012-08-16 12:31:10 +02:00
|
|
|
void fatal(char *s);
|
2012-01-07 00:00:36 +01:00
|
|
|
void initialise_configuration();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void takesig(int sig){
|
|
|
|
int i, status;
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
switch(sig){
|
|
|
|
case SIGHUP:
|
|
|
|
initialise_configuration();
|
2012-08-16 12:15:14 +02:00
|
|
|
if(read_key(&cfg)) fatal(ERR_READING_KEY);
|
2012-01-07 00:00:36 +01:00
|
|
|
kill_children(SIGHUP);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGTERM:
|
|
|
|
quit = 1;
|
2012-10-29 10:22:31 +01:00
|
|
|
p_clean_exit();
|
2012-01-07 00:00:36 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SIGCHLD:
|
|
|
|
while((pid = waitpid (-1, &status, WNOHANG)) > 0){
|
|
|
|
|
|
|
|
//syslog(LOG_PRIORITY, "child (pid: %d) has died", pid);
|
|
|
|
|
|
|
|
if(quit == 0){
|
|
|
|
i = search_slot_by_pid(pid);
|
|
|
|
if(i >= 0){
|
2015-05-09 14:31:20 +02:00
|
|
|
children[i].serial = i;
|
2012-01-07 00:00:36 +01:00
|
|
|
children[i].status = READY;
|
|
|
|
children[i].pid = child_make(&children[i]);
|
|
|
|
}
|
|
|
|
else syslog(LOG_PRIORITY, "error: couldn't find slot for pid %d", pid);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void child_sighup_handler(int sig){
|
|
|
|
if(sig == SIGHUP){
|
|
|
|
received_sighup = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-26 22:18:18 +02:00
|
|
|
int process_email(char *filename, struct session_data *sdata, struct __data *data, int size, struct __config *cfg){
|
|
|
|
int rc;
|
|
|
|
char *status=S_STATUS_UNDEF;
|
|
|
|
char *arule;
|
|
|
|
struct timezone tz;
|
|
|
|
struct timeval tv1, tv2;
|
|
|
|
struct parser_state parser_state;
|
|
|
|
struct counters counters;
|
|
|
|
|
|
|
|
gettimeofday(&tv1, &tz);
|
|
|
|
|
|
|
|
bzero(&counters, sizeof(counters));
|
|
|
|
|
|
|
|
init_session_data(sdata, cfg);
|
|
|
|
|
|
|
|
sdata->tot_len = size;
|
|
|
|
|
|
|
|
/*if(data->import->extra_recipient){
|
|
|
|
snprintf(sdata->rcptto[0], SMALLBUFSIZE-1, "%s", data->import->extra_recipient);
|
|
|
|
sdata->num_of_rcpt_to = 1;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
parser_state = parse_message(sdata, 1, data, cfg);
|
|
|
|
post_parse(sdata, &parser_state, cfg);
|
|
|
|
|
|
|
|
arule = check_againt_ruleset(data->archiving_rules, &parser_state, sdata->tot_len, sdata->spam_message);
|
|
|
|
|
|
|
|
if(arule){
|
|
|
|
syslog(LOG_PRIORITY, "%s: discarding: archiving policy: *%s*", filename, arule);
|
|
|
|
rc = ERR_DISCARDED;
|
|
|
|
remove_stripped_attachments(&parser_state);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
make_digests(sdata, cfg);
|
|
|
|
|
|
|
|
if(sdata->hdr_len < 10){
|
|
|
|
syslog(LOG_PRIORITY, "%s: invalid message, hdr_len: %d", filename, sdata->hdr_len);
|
|
|
|
rc = ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = process_message(sdata, &parser_state, data, cfg);
|
|
|
|
unlink(parser_state.message_id_hash);
|
|
|
|
}
|
|
|
|
|
|
|
|
unlink(sdata->tmpframe);
|
|
|
|
|
|
|
|
|
|
|
|
if(rc == OK){
|
|
|
|
status = S_STATUS_STORED;
|
|
|
|
counters.c_rcvd = 1;
|
|
|
|
counters.c_size += sdata->tot_len;
|
|
|
|
counters.c_stored_size = sdata->stored_len;
|
|
|
|
}
|
|
|
|
else if(rc == ERR_EXISTS){
|
|
|
|
status = S_STATUS_DUPLICATE;
|
|
|
|
counters.c_duplicate = 1;
|
|
|
|
syslog(LOG_PRIORITY, "%s: discarding: duplicate message, id: %llu, message-id: %s", filename, sdata->duplicate_id, parser_state.message_id);
|
|
|
|
}
|
|
|
|
else if(rc == ERR_DISCARDED){
|
|
|
|
status = S_STATUS_DISCARDED;
|
|
|
|
counters.c_ignore = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
status = S_STATUS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(rc != ERR) unlink(filename);
|
|
|
|
|
|
|
|
update_counters(sdata, data, &counters, cfg);
|
|
|
|
|
|
|
|
gettimeofday(&tv2, &tz);
|
|
|
|
|
|
|
|
syslog(LOG_PRIORITY, "%s: from=%s, size=%d/%d, attachments=%d, reference=%s, message-id=%s, retention=%d, folder=%d, delay=%.4f, status=%s",
|
|
|
|
filename, sdata->fromemail, sdata->tot_len,
|
|
|
|
sdata->stored_len, parser_state.n_attachments,
|
|
|
|
parser_state.reference, parser_state.message_id,
|
|
|
|
parser_state.retention, data->folder, tvdiff(tv2,tv1)/1000000.0, status);
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-10-26 21:26:20 +02:00
|
|
|
int process_dir(char *directory, struct session_data *sdata, struct __data *data, struct __config *cfg){
|
|
|
|
DIR *dir;
|
|
|
|
struct dirent *de;
|
|
|
|
int rc=ERR, tot_msgs=0;
|
|
|
|
char fname[SMALLBUFSIZE];
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
dir = opendir(directory);
|
|
|
|
if(!dir){
|
|
|
|
syslog(LOG_PRIORITY, "cannot open directory: %s", directory);
|
|
|
|
return tot_msgs;
|
|
|
|
}
|
|
|
|
|
|
|
|
while((de = readdir(dir))){
|
|
|
|
if(strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue;
|
|
|
|
|
|
|
|
snprintf(fname, sizeof(fname)-1, "%s/%s", directory, de->d_name);
|
|
|
|
|
|
|
|
if(stat(fname, &st) == 0){
|
|
|
|
if(S_ISREG(st.st_mode)){
|
2016-10-26 22:18:18 +02:00
|
|
|
rc = process_email(fname, sdata, data, st.st_size, cfg);
|
2016-10-26 21:26:20 +02:00
|
|
|
|
2016-10-26 22:18:18 +02:00
|
|
|
if(rc == OK || rc == ERR_EXISTS){
|
2016-10-26 21:26:20 +02:00
|
|
|
tot_msgs++;
|
2016-10-26 22:18:18 +02:00
|
|
|
unlink(fname);
|
2016-10-26 21:26:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
//Oct 25 20:37:55 f5e88a047257 piler[3236]: 1/40000000580fc29234488f440fdc735c1869: size=172527/128280, delay=36067, status=stored
|
2016-10-26 22:18:18 +02:00
|
|
|
//syslog(LOG_PRIORITY, "%s: size=%d/%d, delay=%ld, status=%s", fname, sdata->tot_len, sdata->stored_len, tvdiff(tv2, tv1), status);
|
2016-10-26 21:26:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
syslog(LOG_PRIORITY, "ERROR: cannot stat: %s", fname);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
closedir(dir);
|
|
|
|
|
|
|
|
return tot_msgs;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-01-07 00:00:36 +01:00
|
|
|
static void child_main(struct child *ptr){
|
2016-10-23 22:04:55 +02:00
|
|
|
struct session_data sdata;
|
|
|
|
char dir[TINYBUFSIZE];
|
|
|
|
|
2016-10-26 22:18:18 +02:00
|
|
|
/* open directory, then process its files, then sleep 1 sec, and repeat */
|
2012-01-07 00:00:36 +01:00
|
|
|
|
|
|
|
ptr->messages = 0;
|
|
|
|
|
2016-10-23 22:04:55 +02:00
|
|
|
snprintf(dir, sizeof(dir)-1, "%d", ptr->serial);
|
|
|
|
|
|
|
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "child (pid: %d, serial: %d) started main() working on '%s'", getpid(), ptr->serial, dir);
|
2012-01-07 00:00:36 +01:00
|
|
|
|
|
|
|
while(1){
|
|
|
|
if(received_sighup == 1){
|
|
|
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "child (pid: %d) caught HUP signal", getpid());
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-10-23 22:04:55 +02:00
|
|
|
sig_block(SIGHUP);
|
2013-04-02 16:35:32 +02:00
|
|
|
|
2016-10-23 22:04:55 +02:00
|
|
|
if(open_database(&sdata, &cfg) == OK){
|
2016-10-26 21:26:20 +02:00
|
|
|
ptr->messages += process_dir(dir, &sdata, &data, &cfg);
|
2016-10-23 22:04:55 +02:00
|
|
|
close_database(&sdata);
|
2013-04-02 16:35:32 +02:00
|
|
|
|
2016-10-26 22:18:18 +02:00
|
|
|
sleep(1);
|
2016-10-23 22:04:55 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
syslog(LOG_PRIORITY, "ERROR: cannot open database");
|
|
|
|
sleep(10);
|
|
|
|
}
|
2012-01-07 00:00:36 +01:00
|
|
|
|
|
|
|
sig_unblock(SIGHUP);
|
|
|
|
|
2016-10-23 22:04:55 +02:00
|
|
|
// TODO: do we want to quit after processing a certain number of messages?
|
2012-01-07 00:00:36 +01:00
|
|
|
|
2016-10-23 22:04:55 +02:00
|
|
|
//if(cfg.max_requests_per_child > 0 && ptr->messages >= cfg.max_requests_per_child){
|
|
|
|
// if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "child (pid: %d, serial: %d) served enough: %d", getpid(), ptr->messages, ptr->serial);
|
|
|
|
// break;
|
|
|
|
//}
|
2012-01-07 00:00:36 +01:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HAVE_MEMCACHED
|
|
|
|
memcached_shutdown(&(data.memc));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "child decides to exit (pid: %d)", getpid());
|
|
|
|
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static pid_t child_make(struct child *ptr){
|
|
|
|
pid_t pid;
|
|
|
|
|
|
|
|
if((pid = fork()) > 0) return pid;
|
|
|
|
|
|
|
|
if(pid == -1) return -1;
|
|
|
|
|
|
|
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "forked a child (pid: %d)", getpid());
|
|
|
|
|
|
|
|
/* reset signals */
|
|
|
|
|
|
|
|
set_signal_handler(SIGCHLD, SIG_DFL);
|
|
|
|
set_signal_handler(SIGTERM, SIG_DFL);
|
|
|
|
set_signal_handler(SIGHUP, child_sighup_handler);
|
|
|
|
|
|
|
|
child_main(ptr);
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int child_pool_create(){
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0; i<MAXCHILDREN; i++){
|
|
|
|
children[i].pid = 0;
|
|
|
|
children[i].messages = 0;
|
|
|
|
children[i].status = UNDEF;
|
2015-05-09 14:31:20 +02:00
|
|
|
children[i].serial = -1;
|
2012-01-07 00:00:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
for(i=0; i<cfg.number_of_worker_processes; i++){
|
|
|
|
children[i].status = READY;
|
2015-05-09 14:31:20 +02:00
|
|
|
children[i].serial = i;
|
2012-01-07 00:00:36 +01:00
|
|
|
children[i].pid = child_make(&children[i]);
|
|
|
|
|
|
|
|
if(children[i].pid == -1){
|
|
|
|
syslog(LOG_PRIORITY, "error: failed to fork a child");
|
2012-10-29 10:22:31 +01:00
|
|
|
p_clean_exit();
|
2012-01-07 00:00:36 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int search_slot_by_pid(pid_t pid){
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0; i<MAXCHILDREN; i++){
|
|
|
|
if(children[i].pid == pid) return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void kill_children(int sig){
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for(i=0; i<MAXCHILDREN; i++){
|
|
|
|
if(children[i].status != UNDEF && children[i].pid > 1){
|
|
|
|
if(cfg.verbosity >= _LOG_DEBUG) syslog(LOG_PRIORITY, "sending signal to child (pid: %d)", children[i].pid);
|
|
|
|
kill(children[i].pid, sig);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-11-14 15:57:52 +01:00
|
|
|
|
2012-10-29 10:22:31 +01:00
|
|
|
void p_clean_exit(){
|
2011-11-14 15:57:52 +01:00
|
|
|
if(sd != -1) close(sd);
|
|
|
|
|
2012-01-07 00:00:36 +01:00
|
|
|
kill_children(SIGTERM);
|
|
|
|
|
2013-08-14 14:24:30 +02:00
|
|
|
clearrules(data.archiving_rules);
|
|
|
|
clearrules(data.retention_rules);
|
2015-08-28 22:50:28 +02:00
|
|
|
clearrules(data.folder_rules);
|
2011-11-19 21:25:44 +01:00
|
|
|
|
2013-08-14 14:24:30 +02:00
|
|
|
clearhash(data.mydomains);
|
2013-07-12 22:54:45 +02:00
|
|
|
|
2011-11-14 15:57:52 +01:00
|
|
|
syslog(LOG_PRIORITY, "%s has been terminated", PROGNAME);
|
|
|
|
|
|
|
|
unlink(cfg.pidfile);
|
|
|
|
|
2015-05-09 14:31:20 +02:00
|
|
|
if(data.dedup != MAP_FAILED) munmap(data.dedup, MAXCHILDREN*DIGEST_LENGTH*2);
|
|
|
|
|
2011-11-14 15:57:52 +01:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void fatal(char *s){
|
|
|
|
syslog(LOG_PRIORITY, "%s\n", s);
|
2012-10-29 10:22:31 +01:00
|
|
|
p_clean_exit();
|
2011-11-14 15:57:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-11-19 21:25:44 +01:00
|
|
|
void initialise_configuration(){
|
|
|
|
struct session_data sdata;
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
cfg = read_config(configfile);
|
|
|
|
|
2016-10-26 21:26:20 +02:00
|
|
|
if(cfg.number_of_worker_processes < 2) cfg.number_of_worker_processes = 2;
|
2012-01-07 00:00:36 +01:00
|
|
|
if(cfg.number_of_worker_processes > MAXCHILDREN) cfg.number_of_worker_processes = MAXCHILDREN;
|
|
|
|
|
2011-11-14 15:57:52 +01:00
|
|
|
if(strlen(cfg.username) > 1){
|
|
|
|
pwd = getpwnam(cfg.username);
|
|
|
|
if(!pwd) fatal(ERR_NON_EXISTENT_USER);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(getuid() == 0 && pwd){
|
|
|
|
check_and_create_directories(&cfg, pwd->pw_uid, pwd->pw_gid);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if(chdir(cfg.workdir)){
|
|
|
|
syslog(LOG_PRIORITY, "workdir: *%s*", cfg.workdir);
|
|
|
|
fatal(ERR_CHDIR);
|
|
|
|
}
|
|
|
|
|
|
|
|
setlocale(LC_MESSAGES, cfg.locale);
|
|
|
|
setlocale(LC_CTYPE, cfg.locale);
|
|
|
|
|
2011-11-19 21:25:44 +01:00
|
|
|
|
2013-08-14 14:24:30 +02:00
|
|
|
clearrules(data.archiving_rules);
|
|
|
|
clearrules(data.retention_rules);
|
2015-08-28 22:50:28 +02:00
|
|
|
clearrules(data.folder_rules);
|
2012-02-19 22:59:47 +01:00
|
|
|
|
2013-08-14 14:24:30 +02:00
|
|
|
clearhash(data.mydomains);
|
2013-07-12 22:54:45 +02:00
|
|
|
|
2012-08-23 10:23:58 +02:00
|
|
|
data.folder = 0;
|
2012-09-03 17:12:02 +02:00
|
|
|
data.recursive_folder_names = 0;
|
2014-01-13 13:06:10 +01:00
|
|
|
|
2013-08-14 14:24:30 +02:00
|
|
|
inithash(data.mydomains);
|
|
|
|
initrules(data.archiving_rules);
|
|
|
|
initrules(data.retention_rules);
|
2015-08-28 22:50:28 +02:00
|
|
|
initrules(data.folder_rules);
|
2013-07-12 22:54:45 +02:00
|
|
|
|
2013-04-28 14:18:09 +02:00
|
|
|
if(open_database(&sdata, &cfg) == ERR){
|
2011-11-19 21:25:44 +01:00
|
|
|
syslog(LOG_PRIORITY, "cannot connect to mysql server");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-04-05 21:10:09 +02:00
|
|
|
load_rules(&sdata, &data, data.archiving_rules, SQL_ARCHIVING_RULE_TABLE);
|
|
|
|
load_rules(&sdata, &data, data.retention_rules, SQL_RETENTION_RULE_TABLE);
|
|
|
|
load_rules(&sdata, &data, data.folder_rules, SQL_FOLDER_RULE_TABLE);
|
2011-11-19 21:25:44 +01:00
|
|
|
|
2013-01-06 22:16:21 +01:00
|
|
|
load_mydomains(&sdata, &data, &cfg);
|
|
|
|
|
2013-02-15 20:14:35 +01:00
|
|
|
if(cfg.server_id > 0) insert_offset(&sdata, cfg.server_id);
|
|
|
|
|
2013-04-28 14:18:09 +02:00
|
|
|
close_database(&sdata);
|
2011-11-19 21:25:44 +01:00
|
|
|
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
syslog(LOG_PRIORITY, "reloaded config: %s", configfile);
|
|
|
|
|
|
|
|
#ifdef HAVE_MEMCACHED
|
|
|
|
memcached_init(&(data.memc), cfg.memcached_servers, 11211);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int main(int argc, char **argv){
|
2015-05-09 14:31:20 +02:00
|
|
|
int i, rc, yes=1, daemonise=0, dedupfd;
|
2013-04-09 14:50:27 +02:00
|
|
|
char port_string[8];
|
2013-04-02 16:35:32 +02:00
|
|
|
struct addrinfo hints, *res;
|
|
|
|
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
while((i = getopt(argc, argv, "c:dvVh")) > 0){
|
|
|
|
switch(i){
|
|
|
|
|
|
|
|
case 'c' :
|
|
|
|
configfile = optarg;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd' :
|
|
|
|
daemonise = 1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'v' :
|
2015-03-18 11:20:46 +01:00
|
|
|
printf("%s build %d\n", VERSION, get_build());
|
|
|
|
return 0;
|
|
|
|
|
2011-11-14 15:57:52 +01:00
|
|
|
case 'V' :
|
2016-08-31 17:09:33 +02:00
|
|
|
printf("%s %s, build %d, Janos SUTO <sj@acts.hu>\n\n%s\nMySQL client library version: %s\n", PROGNAME, VERSION, get_build(), CONFIGURE_PARAMS, mysql_get_client_info());
|
2015-07-17 14:50:49 +02:00
|
|
|
get_extractor_list();
|
2012-07-06 21:44:57 +02:00
|
|
|
return 0;
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
case 'h' :
|
|
|
|
default :
|
|
|
|
__fatal("usage: ...");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(void) openlog(PROGNAME, LOG_PID, LOG_MAIL);
|
|
|
|
|
2012-08-23 10:23:58 +02:00
|
|
|
data.folder = 0;
|
2012-09-03 17:12:02 +02:00
|
|
|
data.recursive_folder_names = 0;
|
2013-08-14 14:24:30 +02:00
|
|
|
inithash(data.mydomains);
|
|
|
|
initrules(data.archiving_rules);
|
|
|
|
initrules(data.retention_rules);
|
2015-08-28 22:50:28 +02:00
|
|
|
initrules(data.folder_rules);
|
2015-05-09 14:31:20 +02:00
|
|
|
data.dedup = MAP_FAILED;
|
2014-09-18 10:44:45 +02:00
|
|
|
memset(data.starttls, 0, sizeof(data.starttls));
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
|
2011-11-19 21:25:44 +01:00
|
|
|
initialise_configuration();
|
2011-11-14 15:57:52 +01:00
|
|
|
|
2012-01-07 00:00:36 +01:00
|
|
|
set_signal_handler (SIGPIPE, SIG_IGN);
|
|
|
|
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
if(read_key(&cfg)) fatal(ERR_READING_KEY);
|
|
|
|
|
|
|
|
|
2013-04-02 16:35:32 +02:00
|
|
|
memset(&hints, 0, sizeof(hints));
|
|
|
|
hints.ai_family = AF_UNSPEC;
|
|
|
|
hints.ai_socktype = SOCK_STREAM;
|
2011-11-14 15:57:52 +01:00
|
|
|
|
2013-04-02 16:35:32 +02:00
|
|
|
snprintf(port_string, sizeof(port_string)-1, "%d", cfg.listen_port);
|
|
|
|
|
2016-10-23 22:04:55 +02:00
|
|
|
//if((rc = getaddrinfo(cfg.listen_addr, port_string, &hints, &res)) != 0){
|
|
|
|
if((rc = getaddrinfo("127.0.0.1", "5678", &hints, &res)) != 0){
|
2013-04-02 16:35:32 +02:00
|
|
|
fprintf(stderr, "getaddrinfo for '%s': %s\n", cfg.listen_addr, gai_strerror(rc));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if((sd = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1)
|
|
|
|
fatal(ERR_OPEN_SOCKET);
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
|
|
|
|
fatal(ERR_SET_SOCK_OPT);
|
|
|
|
|
2013-04-02 16:35:32 +02:00
|
|
|
if(bind(sd, res->ai_addr, res->ai_addrlen) == -1)
|
2011-11-14 15:57:52 +01:00
|
|
|
fatal(ERR_BIND_TO_PORT);
|
|
|
|
|
|
|
|
if(listen(sd, cfg.backlog) == -1)
|
|
|
|
fatal(ERR_LISTEN);
|
|
|
|
|
|
|
|
|
2013-04-02 16:35:32 +02:00
|
|
|
freeaddrinfo(res);
|
|
|
|
|
|
|
|
|
2011-11-14 15:57:52 +01:00
|
|
|
if(drop_privileges(pwd)) fatal(ERR_SETUID);
|
|
|
|
|
2015-05-14 14:35:07 +02:00
|
|
|
if(cfg.mmap_dedup_test == 1){
|
|
|
|
dedupfd = open(MESSAGE_ID_DEDUP_FILE, O_RDWR);
|
|
|
|
if(dedupfd == -1) fatal(ERR_OPEN_DEDUP_FILE);
|
2015-05-09 14:31:20 +02:00
|
|
|
|
2015-05-14 14:35:07 +02:00
|
|
|
data.dedup = mmap(NULL, MAXCHILDREN*DIGEST_LENGTH*2, PROT_READ|PROT_WRITE, MAP_SHARED, dedupfd, 0);
|
|
|
|
close(dedupfd);
|
2015-05-09 14:31:20 +02:00
|
|
|
|
2015-05-14 14:35:07 +02:00
|
|
|
if(data.dedup == MAP_FAILED) syslog(LOG_INFO, "cannot mmap() %s, errno=%d", MESSAGE_ID_DEDUP_FILE, errno);
|
|
|
|
}
|
2011-11-14 15:57:52 +01:00
|
|
|
|
2012-07-06 21:44:57 +02:00
|
|
|
syslog(LOG_PRIORITY, "%s %s, build %d starting", PROGNAME, VERSION, get_build());
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_DAEMON == 1
|
2015-12-28 13:28:19 +01:00
|
|
|
if(daemonise == 1 && daemon(1, 0) == -1) fatal(ERR_DAEMON);
|
2011-11-14 15:57:52 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
write_pid_file(cfg.pidfile);
|
|
|
|
|
|
|
|
|
2012-01-07 00:00:36 +01:00
|
|
|
child_pool_create();
|
2011-11-14 15:57:52 +01:00
|
|
|
|
2012-01-07 00:00:36 +01:00
|
|
|
set_signal_handler(SIGCHLD, takesig);
|
|
|
|
set_signal_handler(SIGTERM, takesig);
|
|
|
|
set_signal_handler(SIGHUP, takesig);
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
|
2012-01-07 00:00:36 +01:00
|
|
|
for(;;){ sleep(1); }
|
2011-11-14 15:57:52 +01:00
|
|
|
|
2012-10-29 10:22:31 +01:00
|
|
|
p_clean_exit();
|
2011-11-14 15:57:52 +01:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|