MailSvr.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:35k
- /*
- * XMail by Davide Libenzi ( Intranet and Internet mail server )
- * Copyright (C) 1999,..,2004 Davide Libenzi
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Davide Libenzi <davidel@xmailserver.org>
- *
- */
- #include "SysInclude.h"
- #include "SysDep.h"
- #include "SvrDefines.h"
- #include "SList.h"
- #include "ShBlocks.h"
- #include "StrUtils.h"
- #include "BuffSock.h"
- #include "MailConfig.h"
- #include "MiscUtils.h"
- #include "ResLocks.h"
- #include "POP3Svr.h"
- #include "SMTPSvr.h"
- #include "SMAILSvr.h"
- #include "PSYNCSvr.h"
- #include "DNS.h"
- #include "DNSCache.h"
- #include "UsrUtils.h"
- #include "SvrUtils.h"
- #include "MessQueue.h"
- #include "SMAILUtils.h"
- #include "QueueUtils.h"
- #include "ExtAliases.h"
- #include "AliasDomain.h"
- #include "MailDomains.h"
- #include "POP3GwLink.h"
- #include "CTRLSvr.h"
- #include "FINGSvr.h"
- #include "LMAILSvr.h"
- #include "DynDNS.h"
- #include "AppDefines.h"
- #include "MailSvr.h"
- #define ENV_MAIN_PATH "MAIL_ROOT"
- #define ENV_CMD_LINE "MAIL_CMD_LINE"
- #define SVR_SHUTDOWN_FILE ".shutdown"
- #define STD_SMAIL_THREADS 16
- #define MAX_SMAIL_THREADS 256
- #define STD_SMAIL_RETRY_TIMEOUT 480
- #define STD_SMAIL_RETRY_INCR_RATIO 16
- #define STD_SMAIL_MAX_RETRY 32
- #define STD_PSYNC_INTERVAL 120
- #define STD_PSYNC_NUM_THREADS 8
- #define MAX_PSYNC_NUM_THREADS 32
- #define STD_POP3_BADLOGIN_WAIT 5
- #define MAX_POP3_THREADS 1024
- #define MAX_SMTP_THREADS 1024
- #define STD_SMTP_MAX_RCPTS 100
- #define MAX_CTRL_THREADS 512
- #define STD_LMAIL_THREADS 3
- #define MAX_LMAIL_THREADS 17
- #define STD_LMAILTHREAD_SLEEP_TIME 2
- #define SVR_EXIT_WAIT 480
- #define STD_SERVER_SESSION_TIMEOUT 90
- #define MAX_CLIENTS_WAIT 300
- #define CTRL_SERVER_SESSION_TIMEOUT 120
- #define SERVER_SLEEP_TIMESLICE 2
- #define SHUTDOWN_CHECK_TIME 2
- #define STD_POP3AUTH_EXPIRE_TIME (15 * 60)
- #define FILTER_TIMEOUT 90
- static void SvrShutdownCleanup(void);
- static int SvrSetShutdown(void);
- static int SvrSetupCTRL(int iArgCount, char *pszArgs[]);
- static void SvrCleanupCTRL(void);
- static int SvrSetupFING(int iArgCount, char *pszArgs[]);
- static void SvrCleanupFING(void);
- static int SvrSetupPOP3(int iArgCount, char *pszArgs[]);
- static void SvrCleanupPOP3(void);
- static int SvrSetupSMTP(int iArgCount, char *pszArgs[]);
- static void SvrCleanupSMTP(void);
- static int SvrSetupSMAIL(int iArgCount, char *pszArgs[]);
- static void SvrCleanupSMAIL(void);
- static int SvrSetupPSYNC(int iArgCount, char *pszArgs[]);
- static void SvrCleanupPSYNC(void);
- static int SvrSetupLMAIL(int iArgCount, char *pszArgs[]);
- static void SvrCleanupLMAIL(void);
- static int SvrSetup(int iArgCount, char *pszArgs[]);
- static void SvrCleanup(void);
- static void SvrBreakHandler(void);
- static char **SvrMergeArgs(int iArgs, char *pszArgs[], int &iArgsCount);
- ///////////////////////////////////////////////////////////////////////////////
- // External visible variabiles
- ///////////////////////////////////////////////////////////////////////////////
- SHB_HANDLE hShbFING;
- SHB_HANDLE hShbCTRL;
- SHB_HANDLE hShbPOP3;
- SHB_HANDLE hShbSMTP;
- SHB_HANDLE hShbSMAIL;
- SHB_HANDLE hShbPSYNC;
- SHB_HANDLE hShbLMAIL;
- char szMailPath[SYS_MAX_PATH];
- QUEUE_HANDLE hSpoolQueue;
- SYS_SEMAPHORE hSyncSem;
- bool bServerDebug;
- int iFilterTimeout = FILTER_TIMEOUT;
- bool bFilterLogEnabled = false;
- int iLogRotateHours = LOG_ROTATE_HOURS;
- int iQueueSplitLevel = STD_QUEUEFS_DIRS_X_LEVEL;
- #ifdef __UNIX__
- int iMailboxType = XMAIL_MAILDIR;
- #else
- int iMailboxType = XMAIL_MAILBOX;
- #endif
- ///////////////////////////////////////////////////////////////////////////////
- // Local visible variabiles
- ///////////////////////////////////////////////////////////////////////////////
- static char szShutdownFile[SYS_MAX_PATH];
- static bool bServerShutdown = false;
- static int iNumSMAILThreads;
- static int iNumLMAILThreads;
- static SYS_THREAD hCTRLThread;
- static SYS_THREAD hFINGThread;
- static SYS_THREAD hPOP3Thread;
- static SYS_THREAD hSMTPThread;
- static SYS_THREAD hSMAILThreads[MAX_SMAIL_THREADS];
- static SYS_THREAD hLMAILThreads[MAX_LMAIL_THREADS];
- static SYS_THREAD hPSYNCThread;
- static void SvrShutdownCleanup(void)
- {
- CheckRemoveFile(szShutdownFile);
- bServerShutdown = false;
- }
- static int SvrSetShutdown(void)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Set the shutdown flag and shutdown the library
- ///////////////////////////////////////////////////////////////////////////////
- bServerShutdown = true;
- SysShutdownLibrary();
- FILE *pFile = fopen(szShutdownFile, "wt");
- if (pFile == NULL) {
- ErrSetErrorCode(ERR_FILE_CREATE, szShutdownFile);
- return (ERR_FILE_CREATE);
- }
- char szShutdownTimeStr[256] = "";
- MscGetTimeStr(szShutdownTimeStr, sizeof(szShutdownTimeStr));
- fprintf(pFile, "%sn", szShutdownTimeStr);
- fclose(pFile);
- return (0);
- }
- static int SvrSetupCTRL(int iArgCount, char *pszArgs[])
- {
- int iPort = STD_CTRL_PORT;
- int iSessionTimeout = CTRL_SERVER_SESSION_TIMEOUT;
- int iNumAddr = 0;
- long lMaxThreads = MAX_CTRL_THREADS;
- unsigned long ulFlags = 0;
- SYS_INET_ADDR SvrAddr[MAX_CTRL_ACCEPT_ADDRESSES];
- for (int ii = 0; ii < iArgCount; ii++) {
- if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'C'))
- continue;
- switch (pszArgs[ii][2]) {
- case ('p'):
- if (++ii < iArgCount)
- iPort = atoi(pszArgs[ii]);
- break;
- case ('t'):
- if (++ii < iArgCount)
- iSessionTimeout = atoi(pszArgs[ii]);
- break;
- case ('l'):
- ulFlags |= CTRLF_LOG_ENABLED;
- break;
- case ('I'):
- if ((++ii < iArgCount) &&
- (MscGetServerAddress(pszArgs[ii], SvrAddr[iNumAddr]) == 0))
- ++iNumAddr;
- break;
- case ('X'):
- if (++ii < iArgCount)
- lMaxThreads = atol(pszArgs[ii]);
- break;
- }
- }
- if ((hShbCTRL = ShbCreateBlock(sizeof(CTRLConfig))) == SHB_INVALID_HANDLE)
- return (ErrGetErrorCode());
- CTRLConfig *pCTRLCfg = (CTRLConfig *) ShbLock(hShbCTRL);
- if (pCTRLCfg == NULL) {
- ErrorPush();
- ShbCloseBlock(hShbCTRL);
- return (ErrorPop());
- }
- pCTRLCfg->iPort = iPort;
- pCTRLCfg->ulFlags = ulFlags;
- pCTRLCfg->lThreadCount = 0;
- pCTRLCfg->lMaxThreads = lMaxThreads;
- pCTRLCfg->iSessionTimeout = iSessionTimeout;
- pCTRLCfg->iTimeout = STD_SERVER_TIMEOUT;
- pCTRLCfg->iNumAddr = iNumAddr;
- for (int nn = 0; nn < iNumAddr; nn++)
- pCTRLCfg->SvrAddr[nn] = SvrAddr[nn];
- ShbUnlock(hShbCTRL);
- if ((hCTRLThread = SysCreateThread(CTRLThreadProc, NULL)) == SYS_INVALID_THREAD) {
- ShbCloseBlock(hShbCTRL);
- return (ErrGetErrorCode());
- }
- return (0);
- }
- static void SvrCleanupCTRL(void)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Stop CTRL Thread
- ///////////////////////////////////////////////////////////////////////////////
- CTRLConfig *pCTRLCfg = (CTRLConfig *) ShbLock(hShbCTRL);
- pCTRLCfg->ulFlags |= CTRLF_STOP_SERVER;
- ShbUnlock(hShbCTRL);
- ///////////////////////////////////////////////////////////////////////////////
- // Wait CTRL
- ///////////////////////////////////////////////////////////////////////////////
- SysWaitThread(hCTRLThread, SVR_EXIT_WAIT);
- ///////////////////////////////////////////////////////////////////////////////
- // Close CTRL Thread
- ///////////////////////////////////////////////////////////////////////////////
- SysCloseThread(hCTRLThread, 1);
- ShbCloseBlock(hShbCTRL);
- }
- static int SvrSetupFING(int iArgCount, char *pszArgs[])
- {
- int iPort = STD_FINGER_PORT;
- int iNumAddr = 0;
- unsigned long ulFlags = 0;
- SYS_INET_ADDR SvrAddr[MAX_FING_ACCEPT_ADDRESSES];
- for (int ii = 0; ii < iArgCount; ii++) {
- if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'F'))
- continue;
- switch (pszArgs[ii][2]) {
- case ('p'):
- if (++ii < iArgCount)
- iPort = atoi(pszArgs[ii]);
- break;
- case ('l'):
- ulFlags |= FINGF_LOG_ENABLED;
- break;
- case ('I'):
- if ((++ii < iArgCount) &&
- (MscGetServerAddress(pszArgs[ii], SvrAddr[iNumAddr]) == 0))
- ++iNumAddr;
- break;
- }
- }
- if ((hShbFING = ShbCreateBlock(sizeof(FINGConfig))) == SHB_INVALID_HANDLE)
- return (ErrGetErrorCode());
- FINGConfig *pFINGCfg = (FINGConfig *) ShbLock(hShbFING);
- if (pFINGCfg == NULL) {
- ShbCloseBlock(hShbFING);
- return (ErrGetErrorCode());
- }
- pFINGCfg->iPort = iPort;
- pFINGCfg->ulFlags = ulFlags;
- pFINGCfg->lThreadCount = 0;
- pFINGCfg->iTimeout = STD_SERVER_TIMEOUT;
- pFINGCfg->iNumAddr = iNumAddr;
- for (int nn = 0; nn < iNumAddr; nn++)
- pFINGCfg->SvrAddr[nn] = SvrAddr[nn];
- ShbUnlock(hShbFING);
- if ((hFINGThread = SysCreateThread(FINGThreadProc, NULL)) == SYS_INVALID_THREAD) {
- ShbCloseBlock(hShbFING);
- return (ErrGetErrorCode());
- }
- return (0);
- }
- static void SvrCleanupFING(void)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Stop FING Thread
- ///////////////////////////////////////////////////////////////////////////////
- FINGConfig *pFINGCfg = (FINGConfig *) ShbLock(hShbFING);
- pFINGCfg->ulFlags |= FINGF_STOP_SERVER;
- ShbUnlock(hShbFING);
- ///////////////////////////////////////////////////////////////////////////////
- // Wait FINGER
- ///////////////////////////////////////////////////////////////////////////////
- SysWaitThread(hFINGThread, SVR_EXIT_WAIT);
- ///////////////////////////////////////////////////////////////////////////////
- // Close FINGER Thread
- ///////////////////////////////////////////////////////////////////////////////
- SysCloseThread(hFINGThread, 1);
- ShbCloseBlock(hShbFING);
- }
- static int SvrSetupPOP3(int iArgCount, char *pszArgs[])
- {
- int iPort = STD_POP3_PORT;
- int iSessionTimeout = STD_SERVER_SESSION_TIMEOUT;
- int iBadLoginWait = STD_POP3_BADLOGIN_WAIT;
- int iNumAddr = 0;
- long lMaxThreads = MAX_POP3_THREADS;
- unsigned long ulFlags = 0;
- SYS_INET_ADDR SvrAddr[MAX_POP3_ACCEPT_ADDRESSES];
- for (int ii = 0; ii < iArgCount; ii++) {
- if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'P'))
- continue;
- switch (pszArgs[ii][2]) {
- case ('p'):
- if (++ii < iArgCount)
- iPort = atoi(pszArgs[ii]);
- break;
- case ('t'):
- if (++ii < iArgCount)
- iSessionTimeout = atoi(pszArgs[ii]);
- break;
- case ('w'):
- if (++ii < iArgCount)
- iBadLoginWait = atoi(pszArgs[ii]);
- break;
- case ('l'):
- ulFlags |= POP3F_LOG_ENABLED;
- break;
- case ('h'):
- ulFlags |= POP3F_HANG_ON_BADLOGIN;
- break;
- case ('I'):
- if ((++ii < iArgCount) &&
- (MscGetServerAddress(pszArgs[ii], SvrAddr[iNumAddr]) == 0))
- ++iNumAddr;
- break;
- case ('X'):
- if (++ii < iArgCount)
- lMaxThreads = atol(pszArgs[ii]);
- break;
- }
- }
- if ((hShbPOP3 = ShbCreateBlock(sizeof(POP3Config))) == SHB_INVALID_HANDLE)
- return (ErrGetErrorCode());
- POP3Config *pPOP3Cfg = (POP3Config *) ShbLock(hShbPOP3);
- if (pPOP3Cfg == NULL) {
- ShbCloseBlock(hShbPOP3);
- return (ErrGetErrorCode());
- }
- pPOP3Cfg->iPort = iPort;
- pPOP3Cfg->ulFlags = ulFlags;
- pPOP3Cfg->lThreadCount = 0;
- pPOP3Cfg->lMaxThreads = lMaxThreads;
- pPOP3Cfg->iSessionTimeout = iSessionTimeout;
- pPOP3Cfg->iTimeout = STD_SERVER_TIMEOUT;
- pPOP3Cfg->iBadLoginWait = iBadLoginWait;
- pPOP3Cfg->iNumAddr = iNumAddr;
- for (int nn = 0; nn < iNumAddr; nn++)
- pPOP3Cfg->SvrAddr[nn] = SvrAddr[nn];
- ShbUnlock(hShbPOP3);
- ///////////////////////////////////////////////////////////////////////////////
- // Remove POP3 lock files
- ///////////////////////////////////////////////////////////////////////////////
- UsrClearPop3LocksDir();
- if ((hPOP3Thread = SysCreateThread(POP3ThreadProc, NULL)) == SYS_INVALID_THREAD) {
- ShbCloseBlock(hShbPOP3);
- return (ErrGetErrorCode());
- }
- return (0);
- }
- static void SvrCleanupPOP3(void)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Stop POP3 Thread
- ///////////////////////////////////////////////////////////////////////////////
- POP3Config *pPOP3Cfg = (POP3Config *) ShbLock(hShbPOP3);
- pPOP3Cfg->ulFlags |= POP3F_STOP_SERVER;
- ShbUnlock(hShbPOP3);
- ///////////////////////////////////////////////////////////////////////////////
- // Wait POP3 Thread
- ///////////////////////////////////////////////////////////////////////////////
- SysWaitThread(hPOP3Thread, SVR_EXIT_WAIT);
- ///////////////////////////////////////////////////////////////////////////////
- // Close POP3 Thread
- ///////////////////////////////////////////////////////////////////////////////
- SysCloseThread(hPOP3Thread, 1);
- ShbCloseBlock(hShbPOP3);
- }
- static int SvrSetupSMTP(int iArgCount, char *pszArgs[])
- {
- int iPort = STD_SMTP_PORT;
- int iSessionTimeout = STD_SERVER_SESSION_TIMEOUT;
- int iMaxRcpts = STD_SMTP_MAX_RCPTS;
- int iNumAddr = 0;
- unsigned int uPopAuthExpireTime = STD_POP3AUTH_EXPIRE_TIME;
- long lMaxThreads = MAX_SMTP_THREADS;
- unsigned long ulFlags = 0;
- SYS_INET_ADDR SvrAddr[MAX_SMTP_ACCEPT_ADDRESSES];
- for (int ii = 0; ii < iArgCount; ii++) {
- if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'S'))
- continue;
- switch (pszArgs[ii][2]) {
- case ('p'):
- if (++ii < iArgCount)
- iPort = atoi(pszArgs[ii]);
- break;
- case ('t'):
- if (++ii < iArgCount)
- iSessionTimeout = atoi(pszArgs[ii]);
- break;
- case ('l'):
- ulFlags |= SMTPF_LOG_ENABLED;
- break;
- case ('I'):
- if ((++ii < iArgCount) &&
- (MscGetServerAddress(pszArgs[ii], SvrAddr[iNumAddr]) == 0))
- ++iNumAddr;
- break;
- case ('X'):
- if (++ii < iArgCount)
- lMaxThreads = atol(pszArgs[ii]);
- break;
- case ('r'):
- if (++ii < iArgCount)
- iMaxRcpts = atoi(pszArgs[ii]);
- break;
- case ('e'):
- if (++ii < iArgCount)
- uPopAuthExpireTime = (unsigned int) atol(pszArgs[ii]);
- break;
- }
- }
- if ((hShbSMTP = ShbCreateBlock(sizeof(SMTPConfig))) == SHB_INVALID_HANDLE)
- return (ErrGetErrorCode());
- SMTPConfig *pSMTPCfg = (SMTPConfig *) ShbLock(hShbSMTP);
- if (pSMTPCfg == NULL) {
- ShbCloseBlock(hShbSMTP);
- return (ErrGetErrorCode());
- }
- pSMTPCfg->iPort = iPort;
- pSMTPCfg->ulFlags = ulFlags;
- pSMTPCfg->lThreadCount = 0;
- pSMTPCfg->lMaxThreads = lMaxThreads;
- pSMTPCfg->iSessionTimeout = iSessionTimeout;
- pSMTPCfg->iTimeout = STD_SERVER_TIMEOUT;
- pSMTPCfg->iMaxRcpts = iMaxRcpts;
- pSMTPCfg->uPopAuthExpireTime = uPopAuthExpireTime;
- pSMTPCfg->iNumAddr = iNumAddr;
- for (int nn = 0; nn < iNumAddr; nn++)
- pSMTPCfg->SvrAddr[nn] = SvrAddr[nn];
- ShbUnlock(hShbSMTP);
- if ((hSMTPThread = SysCreateThread(SMTPThreadProc, NULL)) == SYS_INVALID_THREAD) {
- ShbCloseBlock(hShbSMTP);
- return (ErrGetErrorCode());
- }
- return (0);
- }
- static void SvrCleanupSMTP(void)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Stop SMTP Thread
- ///////////////////////////////////////////////////////////////////////////////
- SMTPConfig *pSMTPCfg = (SMTPConfig *) ShbLock(hShbSMTP);
- pSMTPCfg->ulFlags |= SMTPF_STOP_SERVER;
- ShbUnlock(hShbSMTP);
- ///////////////////////////////////////////////////////////////////////////////
- // Wait SMTP Thread
- ///////////////////////////////////////////////////////////////////////////////
- SysWaitThread(hSMTPThread, SVR_EXIT_WAIT);
- ///////////////////////////////////////////////////////////////////////////////
- // Close SMTP Thread
- ///////////////////////////////////////////////////////////////////////////////
- SysCloseThread(hSMTPThread, 1);
- ShbCloseBlock(hShbSMTP);
- }
- static int SvrSetupSMAIL(int iArgCount, char *pszArgs[])
- {
- int ii;
- int iRetryTimeout = STD_SMAIL_RETRY_TIMEOUT;
- int iRetryIncrRatio = STD_SMAIL_RETRY_INCR_RATIO;
- int iMaxRetry = STD_SMAIL_MAX_RETRY;
- unsigned long ulFlags = 0;
- iNumSMAILThreads = STD_SMAIL_THREADS;
- for (ii = 0; ii < iArgCount; ii++) {
- if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'Q'))
- continue;
- switch (pszArgs[ii][2]) {
- case ('n'):
- if (++ii < iArgCount)
- iNumSMAILThreads = atoi(pszArgs[ii]);
- iNumSMAILThreads = Min(MAX_SMAIL_THREADS, Max(1, iNumSMAILThreads));
- break;
- case ('t'):
- if (++ii < iArgCount)
- iRetryTimeout = atoi(pszArgs[ii]);
- break;
- case ('i'):
- if (++ii < iArgCount)
- iRetryIncrRatio = atoi(pszArgs[ii]);
- break;
- case ('r'):
- if (++ii < iArgCount)
- iMaxRetry = atoi(pszArgs[ii]);
- break;
- case ('l'):
- ulFlags |= SMAILF_LOG_ENABLED;
- break;
- case ('T'):
- if (++ii < iArgCount)
- iFilterTimeout = atoi(pszArgs[ii]);
- break;
- case ('g'):
- bFilterLogEnabled = true;
- break;
- }
- }
- if ((hShbSMAIL = ShbCreateBlock(sizeof(SMAILConfig))) == SHB_INVALID_HANDLE)
- return (ErrGetErrorCode());
- SMAILConfig *pSMAILCfg = (SMAILConfig *) ShbLock(hShbSMAIL);
- if (pSMAILCfg == NULL) {
- ErrorPush();
- ShbCloseBlock(hShbSMAIL);
- return (ErrorPop());
- }
- pSMAILCfg->ulFlags = ulFlags;
- pSMAILCfg->lThreadCount = 0;
- ShbUnlock(hShbSMAIL);
- ///////////////////////////////////////////////////////////////////////////////
- // Initialize queue fs
- ///////////////////////////////////////////////////////////////////////////////
- char szSpoolDir[SYS_MAX_PATH] = "";
- SvrGetSpoolDir(szSpoolDir, sizeof(szSpoolDir));
- if ((hSpoolQueue = QueOpen(szSpoolDir, iMaxRetry, iRetryTimeout, iRetryIncrRatio,
- iQueueSplitLevel)) == INVALID_QUEUE_HANDLE) {
- ErrorPush();
- ShbCloseBlock(hShbSMAIL);
- return (ErrorPop());
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Create mailer threads
- ///////////////////////////////////////////////////////////////////////////////
- for (ii = 0; ii < iNumSMAILThreads; ii++)
- hSMAILThreads[ii] = SysCreateThread(SMAILThreadProc, NULL);
- return (0);
- }
- static void SvrCleanupSMAIL(void)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Stop SMAIL Thread ( and unlock threads wait with "SysReleaseSemaphore" )
- ///////////////////////////////////////////////////////////////////////////////
- SMAILConfig *pSMAILCfg = (SMAILConfig *) ShbLock(hShbSMAIL);
- pSMAILCfg->ulFlags |= SMAILF_STOP_SERVER;
- ShbUnlock(hShbSMAIL);
- ///////////////////////////////////////////////////////////////////////////////
- // Wait SMAIL Threads
- ///////////////////////////////////////////////////////////////////////////////
- int tt;
- for (tt = 0; tt < iNumSMAILThreads; tt++)
- SysWaitThread(hSMAILThreads[tt], SVR_EXIT_WAIT);
- ///////////////////////////////////////////////////////////////////////////////
- // Close SMAIL Threads
- ///////////////////////////////////////////////////////////////////////////////
- for (tt = 0; tt < iNumSMAILThreads; tt++)
- SysCloseThread(hSMAILThreads[tt], 1);
- ShbCloseBlock(hShbSMAIL);
- ///////////////////////////////////////////////////////////////////////////////
- // Close the mail queue
- ///////////////////////////////////////////////////////////////////////////////
- QueClose(hSpoolQueue);
- }
- static int SvrSetupPSYNC(int iArgCount, char *pszArgs[])
- {
- int iSyncInterval = STD_PSYNC_INTERVAL;
- int iNumSyncThreads = STD_PSYNC_NUM_THREADS;
- unsigned long ulFlags = 0;
- for (int ii = 0; ii < iArgCount; ii++) {
- if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'Y'))
- continue;
- switch (pszArgs[ii][2]) {
- case ('i'):
- if (++ii < iArgCount)
- iSyncInterval = atoi(pszArgs[ii]);
- break;
- case ('t'):
- if (++ii < iArgCount)
- iNumSyncThreads = atoi(pszArgs[ii]);
- iNumSyncThreads = Min(MAX_PSYNC_NUM_THREADS, Max(1, iNumSyncThreads));
- break;
- case ('l'):
- ulFlags |= PSYNCF_LOG_ENABLED;
- break;
- }
- }
- if ((hSyncSem =
- SysCreateSemaphore(iNumSyncThreads, SYS_DEFAULT_MAXCOUNT)) == SYS_INVALID_SEMAPHORE)
- return (ErrGetErrorCode());
- if ((hShbPSYNC = ShbCreateBlock(sizeof(PSYNCConfig))) == SHB_INVALID_HANDLE) {
- ErrorPush();
- SysCloseSemaphore(hSyncSem);
- return (ErrorPop());
- }
- PSYNCConfig *pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC);
- if (pPSYNCCfg == NULL) {
- ErrorPush();
- ShbCloseBlock(hShbPSYNC);
- SysCloseSemaphore(hSyncSem);
- return (ErrorPop());
- }
- pPSYNCCfg->ulFlags = ulFlags;
- pPSYNCCfg->lThreadCount = 0;
- pPSYNCCfg->iTimeout = STD_SERVER_TIMEOUT;
- pPSYNCCfg->iSyncInterval = iSyncInterval;
- pPSYNCCfg->iNumSyncThreads = iNumSyncThreads;
- ShbUnlock(hShbPSYNC);
- ///////////////////////////////////////////////////////////////////////////////
- // Remove POP3 links lock files
- ///////////////////////////////////////////////////////////////////////////////
- GwLkClearLinkLocksDir();
- if ((hPSYNCThread = SysCreateThread(PSYNCThreadProc, NULL)) == SYS_INVALID_THREAD) {
- ShbCloseBlock(hShbPSYNC);
- SysCloseSemaphore(hSyncSem);
- return (ErrGetErrorCode());
- }
- return (0);
- }
- static void SvrCleanupPSYNC(void)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Stop PSYNC Thread
- ///////////////////////////////////////////////////////////////////////////////
- PSYNCConfig *pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC);
- pPSYNCCfg->ulFlags |= PSYNCF_STOP_SERVER;
- ShbUnlock(hShbPSYNC);
- ///////////////////////////////////////////////////////////////////////////////
- // Wait PSYNC Thread
- ///////////////////////////////////////////////////////////////////////////////
- SysWaitThread(hPSYNCThread, SVR_EXIT_WAIT);
- ///////////////////////////////////////////////////////////////////////////////
- // Close PSYNC Thread
- ///////////////////////////////////////////////////////////////////////////////
- SysCloseThread(hPSYNCThread, 1);
- ShbCloseBlock(hShbPSYNC);
- SysCloseSemaphore(hSyncSem);
- }
- static int SvrSetupLMAIL(int iArgCount, char *pszArgs[])
- {
- int ii;
- int iSleepTimeout = STD_LMAILTHREAD_SLEEP_TIME;
- unsigned long ulFlags = 0;
- iNumLMAILThreads = STD_LMAIL_THREADS;
- for (ii = 0; ii < iArgCount; ii++) {
- if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'L'))
- continue;
- switch (pszArgs[ii][2]) {
- case ('n'):
- if (++ii < iArgCount)
- iNumLMAILThreads = atoi(pszArgs[ii]);
- iNumLMAILThreads = Min(MAX_LMAIL_THREADS, Max(1, iNumLMAILThreads));
- break;
- case ('l'):
- ulFlags |= LMAILF_LOG_ENABLED;
- break;
- case ('t'):
- if (++ii < iArgCount)
- iSleepTimeout = atoi(pszArgs[ii]);
- break;
- }
- }
- if ((hShbLMAIL = ShbCreateBlock(sizeof(LMAILConfig))) == SHB_INVALID_HANDLE)
- return (ErrGetErrorCode());
- LMAILConfig *pLMAILCfg = (LMAILConfig *) ShbLock(hShbLMAIL);
- if (pLMAILCfg == NULL) {
- ErrorPush();
- ShbCloseBlock(hShbLMAIL);
- return (ErrorPop());
- }
- pLMAILCfg->ulFlags = ulFlags;
- pLMAILCfg->iSleepTimeout = iSleepTimeout;
- pLMAILCfg->lNumThreads = iNumLMAILThreads;
- pLMAILCfg->lThreadCount = 0;
- ShbUnlock(hShbLMAIL);
- ///////////////////////////////////////////////////////////////////////////////
- // Create mailer threads
- ///////////////////////////////////////////////////////////////////////////////
- for (ii = 0; ii < iNumLMAILThreads; ii++)
- hLMAILThreads[ii] = SysCreateThread(LMAILThreadProc, NULL);
- return (0);
- }
- static void SvrCleanupLMAIL(void)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Stop LMAIL Thread ( and unlock threads wait with "SysReleaseSemaphore" )
- ///////////////////////////////////////////////////////////////////////////////
- LMAILConfig *pLMAILCfg = (LMAILConfig *) ShbLock(hShbLMAIL);
- pLMAILCfg->ulFlags |= LMAILF_STOP_SERVER;
- ShbUnlock(hShbLMAIL);
- ///////////////////////////////////////////////////////////////////////////////
- // Wait LMAIL Threads
- ///////////////////////////////////////////////////////////////////////////////
- int tt;
- for (tt = 0; tt < iNumLMAILThreads; tt++)
- SysWaitThread(hLMAILThreads[tt], SVR_EXIT_WAIT);
- ///////////////////////////////////////////////////////////////////////////////
- // Close LMAIL Threads
- ///////////////////////////////////////////////////////////////////////////////
- for (tt = 0; tt < iNumLMAILThreads; tt++)
- SysCloseThread(hLMAILThreads[tt], 1);
- ShbCloseBlock(hShbLMAIL);
- }
- static int SvrSetup(int iArgCount, char *pszArgs[])
- {
- StrSNCpy(szMailPath, SYS_BASE_FS_STR);
- char *pszValue = SysGetEnv(ENV_MAIN_PATH);
- if (pszValue != NULL) {
- if (strncmp(szMailPath, pszValue, strlen(szMailPath)) == 0)
- StrSNCpy(szMailPath, pszValue);
- else
- StrSNCat(szMailPath, pszValue);
- DelFinalSlash(szMailPath);
- SysFree(pszValue);
- }
- bServerDebug = false;
- int iSndBufSize = -1;
- int iRcvBufSize = -1;
- int iDnsCacheDirs = DNS_HASH_NUM_DIRS;
- for (int ii = 0; ii < iArgCount; ii++) {
- if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'M'))
- continue;
- switch (pszArgs[ii][2]) {
- case ('s'):
- if (++ii < iArgCount) {
- StrSNCpy(szMailPath, pszArgs[ii]);
- DelFinalSlash(szMailPath);
- }
- break;
- case ('d'):
- bServerDebug = true;
- break;
- case ('r'):
- if (++ii < iArgCount)
- iLogRotateHours = atoi(pszArgs[ii]);
- break;
- case ('x'):
- if (++ii < iArgCount) {
- iQueueSplitLevel = atoi(pszArgs[ii]);
- while (!IsPrimeNumber(iQueueSplitLevel))
- ++iQueueSplitLevel;
- }
- break;
- case ('R'):
- if (++ii < iArgCount) {
- iRcvBufSize = atoi(pszArgs[ii]);
- iRcvBufSize = NbrCeil(iRcvBufSize, 1024);
- }
- break;
- case ('S'):
- if (++ii < iArgCount) {
- iSndBufSize = atoi(pszArgs[ii]);
- iSndBufSize = NbrCeil(iSndBufSize, 1024);
- }
- break;
- case ('M'):
- iMailboxType = XMAIL_MAILDIR;
- break;
- case ('m'):
- iMailboxType = XMAIL_MAILBOX;
- break;
- case ('D'):
- if (++ii < iArgCount)
- iDnsCacheDirs = atoi(pszArgs[ii]);
- break;
- }
- }
- if ((strlen(szMailPath) == 0) || !SysExistDir(szMailPath)) {
- ErrSetErrorCode(ERR_CONF_PATH);
- return (ERR_CONF_PATH);
- }
- AppendSlash(szMailPath);
- ///////////////////////////////////////////////////////////////////////////////
- // Setup library socket buffers
- ///////////////////////////////////////////////////////////////////////////////
- SysSetupSocketBuffers((iSndBufSize > 0) ? &iSndBufSize : NULL,
- (iRcvBufSize > 0) ? &iRcvBufSize : NULL);
- ///////////////////////////////////////////////////////////////////////////////
- // Setup shutdown file name ( must be called before any shutdown function )
- ///////////////////////////////////////////////////////////////////////////////
- sprintf(szShutdownFile, "%s%s", szMailPath, SVR_SHUTDOWN_FILE);
- ///////////////////////////////////////////////////////////////////////////////
- // Setup resource lockers
- ///////////////////////////////////////////////////////////////////////////////
- if (RLckInitLockers() < 0)
- return (ErrGetErrorCode());
- ///////////////////////////////////////////////////////////////////////////////
- // Check dynamic DNS setup
- ///////////////////////////////////////////////////////////////////////////////
- if (DynDnsSetup() < 0) {
- ErrorPush();
- RLckCleanupLockers();
- return (ErrorPop());
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Clear shutdown condition
- ///////////////////////////////////////////////////////////////////////////////
- SvrShutdownCleanup();
- ///////////////////////////////////////////////////////////////////////////////
- // Align table indexes
- ///////////////////////////////////////////////////////////////////////////////
- if ((UsrCheckUsersIndexes() < 0) ||
- (UsrCheckAliasesIndexes() < 0) ||
- (ExAlCheckAliasIndexes() < 0) ||
- (MDomCheckDomainsIndexes() < 0) || (ADomCheckDomainsIndexes() < 0)) {
- ErrorPush();
- RLckCleanupLockers();
- return (ErrorPop());
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Initialize DNS cache
- ///////////////////////////////////////////////////////////////////////////////
- if (CDNS_Initialize(iDnsCacheDirs) < 0) {
- ErrorPush();
- RLckCleanupLockers();
- return (ErrorPop());
- }
- return (0);
- }
- static void SvrCleanup(void)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Cleanup resource lockers
- ///////////////////////////////////////////////////////////////////////////////
- RLckCleanupLockers();
- ///////////////////////////////////////////////////////////////////////////////
- // Clear shutdown condition
- ///////////////////////////////////////////////////////////////////////////////
- SvrShutdownCleanup();
- }
- static void SvrBreakHandler(void)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Set shutdown condition
- ///////////////////////////////////////////////////////////////////////////////
- SvrSetShutdown();
- }
- static char **SvrMergeArgs(int iArgs, char *pszArgs[], int &iArgsCount)
- {
- int iCmdArgs = 0;
- char **ppszCmdArgs = NULL;
- char *pszCmdLine = SysGetEnv(ENV_CMD_LINE);
- if (pszCmdLine != NULL) {
- ppszCmdArgs = StrGetArgs(pszCmdLine, iCmdArgs);
- SysFree(pszCmdLine);
- }
- char **ppszMergeArgs = (char **) SysAlloc((iCmdArgs + iArgs + 1) * sizeof(char *));
- if (ppszMergeArgs == NULL) {
- if (ppszCmdArgs != NULL)
- StrFreeStrings(ppszCmdArgs);
- return (NULL);
- }
- iArgsCount = 0;
- for (int ii = 0; ii < iArgs; ii++, iArgsCount++)
- ppszMergeArgs[iArgsCount] = SysStrDup(pszArgs[ii]);
- for (int jj = 0; jj < iCmdArgs; jj++, iArgsCount++)
- ppszMergeArgs[iArgsCount] = SysStrDup(ppszCmdArgs[jj]);
- ppszMergeArgs[iArgsCount] = NULL;
- if (ppszCmdArgs != NULL)
- StrFreeStrings(ppszCmdArgs);
- return (ppszMergeArgs);
- }
- int SvrMain(int iArgCount, char *pszArgs[])
- {
- if (SysInitLibrary() < 0) {
- ErrorPush();
- SysEventLog(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
- return (ErrorPop());
- }
- int iMergeArgsCount = 0;
- char **ppszMergeArgs = SvrMergeArgs(iArgCount, pszArgs, iMergeArgsCount);
- if (ppszMergeArgs == NULL) {
- ErrorPush();
- SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
- SysCleanupLibrary();
- return (ErrorPop());
- }
- if (SvrSetup(iMergeArgsCount, ppszMergeArgs) < 0) {
- ErrorPush();
- SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
- StrFreeStrings(ppszMergeArgs);
- SysCleanupLibrary();
- return (ErrorPop());
- }
- if (SvrSetupSMAIL(iMergeArgsCount, ppszMergeArgs) < 0) {
- ErrorPush();
- SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
- StrFreeStrings(ppszMergeArgs);
- SvrCleanup();
- SysCleanupLibrary();
- return (ErrorPop());
- }
- if (SvrSetupCTRL(iMergeArgsCount, ppszMergeArgs) < 0) {
- ErrorPush();
- SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
- SvrCleanupSMAIL();
- StrFreeStrings(ppszMergeArgs);
- SvrCleanup();
- SysCleanupLibrary();
- return (ErrorPop());
- }
- if (SvrSetupPOP3(iMergeArgsCount, ppszMergeArgs) < 0) {
- ErrorPush();
- SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
- SvrCleanupCTRL();
- SvrCleanupSMAIL();
- StrFreeStrings(ppszMergeArgs);
- SvrCleanup();
- SysCleanupLibrary();
- return (ErrorPop());
- }
- if (SvrSetupSMTP(iMergeArgsCount, ppszMergeArgs) < 0) {
- ErrorPush();
- SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
- SvrCleanupPOP3();
- SvrCleanupCTRL();
- SvrCleanupSMAIL();
- StrFreeStrings(ppszMergeArgs);
- SvrCleanup();
- SysCleanupLibrary();
- return (ErrorPop());
- }
- if (SvrSetupPSYNC(iMergeArgsCount, ppszMergeArgs) < 0) {
- ErrorPush();
- SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
- SvrCleanupSMTP();
- SvrCleanupPOP3();
- SvrCleanupCTRL();
- SvrCleanupSMAIL();
- StrFreeStrings(ppszMergeArgs);
- SvrCleanup();
- SysCleanupLibrary();
- return (ErrorPop());
- }
- if (SvrSetupFING(iMergeArgsCount, ppszMergeArgs) < 0) {
- ErrorPush();
- SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
- SvrCleanupPSYNC();
- SvrCleanupSMTP();
- SvrCleanupPOP3();
- SvrCleanupCTRL();
- SvrCleanupSMAIL();
- StrFreeStrings(ppszMergeArgs);
- SvrCleanup();
- SysCleanupLibrary();
- return (ErrorPop());
- }
- if (SvrSetupLMAIL(iMergeArgsCount, ppszMergeArgs) < 0) {
- ErrorPush();
- SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
- SvrCleanupFING();
- SvrCleanupPSYNC();
- SvrCleanupSMTP();
- SvrCleanupPOP3();
- SvrCleanupCTRL();
- SvrCleanupSMAIL();
- StrFreeStrings(ppszMergeArgs);
- SvrCleanup();
- SysCleanupLibrary();
- return (ErrorPop());
- }
- StrFreeStrings(ppszMergeArgs);
- ///////////////////////////////////////////////////////////////////////////////
- // Set stop handler
- ///////////////////////////////////////////////////////////////////////////////
- SysSetBreakHandler(SvrBreakHandler);
- ///////////////////////////////////////////////////////////////////////////////
- // Server main loop
- ///////////////////////////////////////////////////////////////////////////////
- for (; !SvrInShutdown(true);) {
- SysSleep(SERVER_SLEEP_TIMESLICE);
- }
- ///////////////////////////////////////////////////////////////////////////////
- // Goodbye cleanups
- ///////////////////////////////////////////////////////////////////////////////
- SvrCleanupLMAIL();
- SvrCleanupFING();
- SvrCleanupPSYNC();
- SvrCleanupSMTP();
- SvrCleanupPOP3();
- SvrCleanupCTRL();
- SvrCleanupSMAIL();
- SvrCleanup();
- SysLogMessage(LOG_LEV_MESSAGE, APP_NAME_VERSION_STR " server stoppedn");
- SysCleanupLibrary();
- return (0);
- }
- int SvrStopServer(bool bWait)
- {
- ///////////////////////////////////////////////////////////////////////////////
- // Set shutdown condition
- ///////////////////////////////////////////////////////////////////////////////
- SvrSetShutdown();
- if (bWait) {
- int iWaitTime = 0;
- for (; SvrInShutdown(true); iWaitTime += SERVER_SLEEP_TIMESLICE)
- SysSleep(SERVER_SLEEP_TIMESLICE);
- }
- return (0);
- }
- bool SvrInShutdown(bool bForceCheck)
- {
- time_t tNow = time(NULL);
- static time_t tLastCheck = 0;
- static bool bShutdown = false;
- if (bForceCheck || (tNow > (tLastCheck + SHUTDOWN_CHECK_TIME))) {
- tLastCheck = tNow;
- if (bServerShutdown)
- bShutdown = true;
- else if (SysExistFile(szShutdownFile)) {
- bServerShutdown = true;
- SysShutdownLibrary();
- bShutdown = true;
- }
- }
- return (bShutdown);
- }