diff options
Diffstat (limited to 'timsieved.c')
-rw-r--r-- | timsieved.c | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/timsieved.c b/timsieved.c new file mode 100644 index 00000000..48313439 --- /dev/null +++ b/timsieved.c @@ -0,0 +1,315 @@ +/* $Id$ +* (c) 2000-2002 IC&S, The Netherlands +* +* timsieved.c +* +* main prg for tims daemon +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <errno.h> +#include "imap4.h" +#include "server.h" +#include "debug.h" +#include "misc.h" +#include "dbmail.h" +#include "clientinfo.h" +#include "timsieve.h" +#ifdef PROC_TITLES +#include "proctitleutils.h" +#endif + + +#define PNAME "dbmail/timsieved" + +/* server timeout error */ +#define TIMS_TIMEOUT_MSG "221 Connection timeout BYE" + +struct list smtpItems; +struct list timsItems; +struct list sysItems; + +char *configFile = DEFAULT_CONFIG_FILE; + +/* set up database login data */ +extern db_param_t _db_params; + +void SetConfigItems(serverConfig_t *config, struct list *items); +static int SetMainSigHandler(void); +static void Daemonize(void); +void MainSigHandler(int sig, siginfo_t *info, void *data); + +int tims_before_smtp = 0; +int mainRestart = 0; +int mainStop = 0; + +PopSession_t session; +char *myhostname; +char *timeout_setting; + +#ifdef PROC_TITLES +int main(int argc, char *argv[], char **envp) +#else + int main(int argc, char *argv[]) +#endif +{ + serverConfig_t config; + int result, status; + pid_t pid; + + openlog(PNAME, LOG_PID, LOG_MAIL); + + if (argc >= 2 && (argv[1])) + { + if (strcmp (argv[1],"-v") == 0) + { + printf ("\n*** DBMAIL: dbmail-timsieved version $Revision$ %s\n\n",COPYRIGHT); + return 0; + } + else + if (strcmp(argv[1],"-f")==0 && (argv[2])) + configFile = argv[2]; + } + + SetMainSigHandler(); + Daemonize(); + result = 0; + + do + { + mainStop = 0; + mainRestart = 0; + + trace(TRACE_DEBUG, "main(): reading config"); +#ifdef PROC_TITLES + init_set_proc_title(argc, argv, envp, PNAME); + set_proc_title("%s", "Idle"); +#endif + + /* We need smtp config for bounce.c and forward.c */ + ReadConfig("SMTP", configFile, &smtpItems); + ReadConfig("TIMSIEVED", configFile, &timsItems); + ReadConfig("DBMAIL", configFile, &sysItems); + SetConfigItems(&config, &timsItems); + SetTraceLevel(&timsItems); + GetDBParams(&_db_params, &sysItems); + + config.ClientHandler = tims_handle_connection; + config.timeoutMsg = TIMS_TIMEOUT_MSG; + + CreateSocket(&config); + trace(TRACE_DEBUG, "main(): socket created, starting server"); + + switch ( (pid = fork()) ) + { + case -1: + close(config.listenSocket); + trace(TRACE_FATAL, "main(): fork failed [%s]", strerror(errno)); + + case 0: + /* child process */ + drop_privileges(config.serverUser, config.serverGroup); + result = StartServer(&config); + + trace(TRACE_INFO, "main(): server done, exit."); + exit(result); + + default: + /* parent process, wait for child to exit */ + while (waitpid(pid, &status, WNOHANG|WUNTRACED) == 0) + { + if (mainStop) + kill(pid, SIGTERM); + + if (mainRestart) + kill(pid, SIGHUP); + + sleep(2); + } + + if (WIFEXITED(status)) + { + /* child process terminated neatly */ + result = WEXITSTATUS(status); + trace(TRACE_DEBUG, "main(): server has exited, exit status [%d]", result); + } + else + { + /* child stopped or signaled, don't like */ + /* make sure it is dead */ + trace(TRACE_DEBUG, "main(): server has not exited normally. Killing.."); + + kill(pid, SIGKILL); + result = 0; + } + } + + list_freelist(&smtpItems.start); + list_freelist(&timsItems.start); + list_freelist(&sysItems.start); + close(config.listenSocket); + + } while (result == 1 && !mainStop) ; /* 1 means reread-config and restart */ + + trace(TRACE_INFO, "main(): exit"); + return 0; +} + + +void MainSigHandler(int sig, siginfo_t *info, void *data) +{ + trace(TRACE_DEBUG, "MainSigHandler(): got signal [%d]", sig); + + if (sig == SIGHUP) + mainRestart = 1; + else + mainStop = 1; +} + + +void Daemonize() +{ + if (fork()) + exit(0); + setsid(); + + if (fork()) + exit(0); +} + + +int SetMainSigHandler() +{ + struct sigaction act; + + /* init & install signal handlers */ + memset(&act, 0, sizeof(act)); + + act.sa_sigaction = MainSigHandler; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + + sigaction(SIGINT, &act, 0); + sigaction(SIGQUIT, &act, 0); + sigaction(SIGTERM, &act, 0); + sigaction(SIGHUP, &act, 0); + + return 0; +} + + +void SetConfigItems(serverConfig_t *config, struct list *items) +{ + field_t val; + + /* read items: NCHILDREN */ + GetConfigValue("NCHILDREN", items, val); + if (strlen(val) == 0) + trace(TRACE_FATAL, "SetConfigItems(): no value for NCHILDREN in config file"); + + if ( (config->nChildren = atoi(val)) <= 0) + trace(TRACE_FATAL, "SetConfigItems(): value for NCHILDREN is invalid: [%d]", config->nChildren); + + trace(TRACE_DEBUG, "SetConfigItems(): server will create [%d] children", config->nChildren); + + + /* read items: MAXCONNECTS */ + GetConfigValue("MAXCONNECTS", items, val); + if (strlen(val) == 0) + trace(TRACE_FATAL, "SetConfigItems(): no value for MAXCONNECTS in config file"); + + if ( (config->childMaxConnect = atoi(val)) <= 0) + trace(TRACE_FATAL, "SetConfigItems(): value for MAXCONNECTS is invalid: [%d]", config->childMaxConnect); + + trace(TRACE_DEBUG, "SetConfigItems(): children will make max. [%d] connections", config->childMaxConnect); + + + /* read items: TIMEOUT */ + GetConfigValue("TIMEOUT", items, val); + if (strlen(val) == 0) + { + trace(TRACE_DEBUG, "SetConfigItems(): no value for TIMEOUT in config file"); + config->timeout = 0; + } + else if ( (config->timeout = atoi(val)) <= 30) + trace(TRACE_FATAL, "SetConfigItems(): value for TIMEOUT is invalid: [%d]", config->timeout); + + trace(TRACE_DEBUG, "SetConfigItems(): timeout [%d] seconds", config->timeout); + + + /* read items: PORT */ + GetConfigValue("PORT", items, val); + if (strlen(val) == 0) + trace(TRACE_FATAL, "SetConfigItems(): no value for PORT in config file"); + + if ( (config->port = atoi(val)) <= 0) + trace(TRACE_FATAL, "SetConfigItems(): value for PORT is invalid: [%d]", config->port); + + trace(TRACE_DEBUG, "SetConfigItems(): binding to PORT [%d]", config->port); + + + /* read items: BINDIP */ + GetConfigValue("BINDIP", items, val); + if (strlen(val) == 0) + trace(TRACE_FATAL, "SetConfigItems(): no value for BINDIP in config file"); + + strncpy(config->ip, val, IPLEN); + config->ip[IPLEN-1] = '\0'; + + trace(TRACE_DEBUG, "SetConfigItems(): binding to IP [%s]", config->ip); + + + /* read items: RESOLVE_IP */ + GetConfigValue("RESOLVE_IP", items, val); + if (strlen(val) == 0) + trace(TRACE_DEBUG, "SetConfigItems(): no value for RESOLVE_IP in config file"); + + config->resolveIP = (strcasecmp(val, "yes") == 0); + + trace(TRACE_DEBUG, "SetConfigItems(): %sresolving client IP", config->resolveIP ? "" : "not "); + + + /* read items: IMAP-BEFORE-SMTP */ + GetConfigValue("TIMS_BEFORE_SMTP", items, val); + if (strlen(val) == 0) + trace(TRACE_DEBUG, "SetConfigItems(): no value for TIMS_BEFORE_SMTP in config file"); + + tims_before_smtp = (strcasecmp(val, "yes") == 0); + + trace(TRACE_DEBUG, "SetConfigItems(): %s TIMS-before-SMTP", + tims_before_smtp ? "Enabling" : "Disabling"); + + + /* read items: EFFECTIVE-USER */ + GetConfigValue("EFFECTIVE_USER", items, val); + if (strlen(val) == 0) + trace(TRACE_FATAL, "SetConfigItems(): no value for EFFECTIVE_USER in config file"); + + strncpy(config->serverUser, val, FIELDSIZE); + config->serverUser[FIELDSIZE-1] = '\0'; + + trace(TRACE_DEBUG, "SetConfigItems(): effective user shall be [%s]", config->serverUser); + + + /* read items: EFFECTIVE-GROUP */ + GetConfigValue("EFFECTIVE_GROUP", items, val); + if (strlen(val) == 0) + trace(TRACE_FATAL, "SetConfigItems(): no value for EFFECTIVE_GROUP in config file"); + + strncpy(config->serverGroup, val, FIELDSIZE); + config->serverGroup[FIELDSIZE-1] = '\0'; + + trace(TRACE_DEBUG, "SetConfigItems(): effective group shall be [%s]", config->serverGroup); + + + +} |