MailSvr.cpp
上传用户:woshihumen
上传日期:2013-07-18
资源大小:484k
文件大小:35k
源码类别:

Email服务器

开发平台:

Visual C++

  1. /*
  2.  *  XMail by Davide Libenzi ( Intranet and Internet mail server )
  3.  *  Copyright (C) 1999,..,2004  Davide Libenzi
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  *  Davide Libenzi <davidel@xmailserver.org>
  20.  *
  21.  */
  22. #include "SysInclude.h"
  23. #include "SysDep.h"
  24. #include "SvrDefines.h"
  25. #include "SList.h"
  26. #include "ShBlocks.h"
  27. #include "StrUtils.h"
  28. #include "BuffSock.h"
  29. #include "MailConfig.h"
  30. #include "MiscUtils.h"
  31. #include "ResLocks.h"
  32. #include "POP3Svr.h"
  33. #include "SMTPSvr.h"
  34. #include "SMAILSvr.h"
  35. #include "PSYNCSvr.h"
  36. #include "DNS.h"
  37. #include "DNSCache.h"
  38. #include "UsrUtils.h"
  39. #include "SvrUtils.h"
  40. #include "MessQueue.h"
  41. #include "SMAILUtils.h"
  42. #include "QueueUtils.h"
  43. #include "ExtAliases.h"
  44. #include "AliasDomain.h"
  45. #include "MailDomains.h"
  46. #include "POP3GwLink.h"
  47. #include "CTRLSvr.h"
  48. #include "FINGSvr.h"
  49. #include "LMAILSvr.h"
  50. #include "DynDNS.h"
  51. #include "AppDefines.h"
  52. #include "MailSvr.h"
  53. #define ENV_MAIN_PATH               "MAIL_ROOT"
  54. #define ENV_CMD_LINE                "MAIL_CMD_LINE"
  55. #define SVR_SHUTDOWN_FILE           ".shutdown"
  56. #define STD_SMAIL_THREADS           16
  57. #define MAX_SMAIL_THREADS           256
  58. #define STD_SMAIL_RETRY_TIMEOUT     480
  59. #define STD_SMAIL_RETRY_INCR_RATIO  16
  60. #define STD_SMAIL_MAX_RETRY         32
  61. #define STD_PSYNC_INTERVAL          120
  62. #define STD_PSYNC_NUM_THREADS       8
  63. #define MAX_PSYNC_NUM_THREADS       32
  64. #define STD_POP3_BADLOGIN_WAIT      5
  65. #define MAX_POP3_THREADS            1024
  66. #define MAX_SMTP_THREADS            1024
  67. #define STD_SMTP_MAX_RCPTS          100
  68. #define MAX_CTRL_THREADS            512
  69. #define STD_LMAIL_THREADS           3
  70. #define MAX_LMAIL_THREADS           17
  71. #define STD_LMAILTHREAD_SLEEP_TIME  2
  72. #define SVR_EXIT_WAIT               480
  73. #define STD_SERVER_SESSION_TIMEOUT  90
  74. #define MAX_CLIENTS_WAIT            300
  75. #define CTRL_SERVER_SESSION_TIMEOUT 120
  76. #define SERVER_SLEEP_TIMESLICE      2
  77. #define SHUTDOWN_CHECK_TIME         2
  78. #define STD_POP3AUTH_EXPIRE_TIME    (15 * 60)
  79. #define FILTER_TIMEOUT              90
  80. static void SvrShutdownCleanup(void);
  81. static int SvrSetShutdown(void);
  82. static int SvrSetupCTRL(int iArgCount, char *pszArgs[]);
  83. static void SvrCleanupCTRL(void);
  84. static int SvrSetupFING(int iArgCount, char *pszArgs[]);
  85. static void SvrCleanupFING(void);
  86. static int SvrSetupPOP3(int iArgCount, char *pszArgs[]);
  87. static void SvrCleanupPOP3(void);
  88. static int SvrSetupSMTP(int iArgCount, char *pszArgs[]);
  89. static void SvrCleanupSMTP(void);
  90. static int SvrSetupSMAIL(int iArgCount, char *pszArgs[]);
  91. static void SvrCleanupSMAIL(void);
  92. static int SvrSetupPSYNC(int iArgCount, char *pszArgs[]);
  93. static void SvrCleanupPSYNC(void);
  94. static int SvrSetupLMAIL(int iArgCount, char *pszArgs[]);
  95. static void SvrCleanupLMAIL(void);
  96. static int SvrSetup(int iArgCount, char *pszArgs[]);
  97. static void SvrCleanup(void);
  98. static void SvrBreakHandler(void);
  99. static char **SvrMergeArgs(int iArgs, char *pszArgs[], int &iArgsCount);
  100. ///////////////////////////////////////////////////////////////////////////////
  101. //  External visible variabiles
  102. ///////////////////////////////////////////////////////////////////////////////
  103. SHB_HANDLE hShbFING;
  104. SHB_HANDLE hShbCTRL;
  105. SHB_HANDLE hShbPOP3;
  106. SHB_HANDLE hShbSMTP;
  107. SHB_HANDLE hShbSMAIL;
  108. SHB_HANDLE hShbPSYNC;
  109. SHB_HANDLE hShbLMAIL;
  110. char szMailPath[SYS_MAX_PATH];
  111. QUEUE_HANDLE hSpoolQueue;
  112. SYS_SEMAPHORE hSyncSem;
  113. bool bServerDebug;
  114. int iFilterTimeout = FILTER_TIMEOUT;
  115. bool bFilterLogEnabled = false;
  116. int iLogRotateHours = LOG_ROTATE_HOURS;
  117. int iQueueSplitLevel = STD_QUEUEFS_DIRS_X_LEVEL;
  118. #ifdef __UNIX__
  119. int iMailboxType = XMAIL_MAILDIR;
  120. #else
  121. int iMailboxType = XMAIL_MAILBOX;
  122. #endif
  123. ///////////////////////////////////////////////////////////////////////////////
  124. //  Local visible variabiles
  125. ///////////////////////////////////////////////////////////////////////////////
  126. static char szShutdownFile[SYS_MAX_PATH];
  127. static bool bServerShutdown = false;
  128. static int iNumSMAILThreads;
  129. static int iNumLMAILThreads;
  130. static SYS_THREAD hCTRLThread;
  131. static SYS_THREAD hFINGThread;
  132. static SYS_THREAD hPOP3Thread;
  133. static SYS_THREAD hSMTPThread;
  134. static SYS_THREAD hSMAILThreads[MAX_SMAIL_THREADS];
  135. static SYS_THREAD hLMAILThreads[MAX_LMAIL_THREADS];
  136. static SYS_THREAD hPSYNCThread;
  137. static void SvrShutdownCleanup(void)
  138. {
  139. CheckRemoveFile(szShutdownFile);
  140. bServerShutdown = false;
  141. }
  142. static int SvrSetShutdown(void)
  143. {
  144. ///////////////////////////////////////////////////////////////////////////////
  145. //  Set the shutdown flag and shutdown the library
  146. ///////////////////////////////////////////////////////////////////////////////
  147. bServerShutdown = true;
  148. SysShutdownLibrary();
  149. FILE *pFile = fopen(szShutdownFile, "wt");
  150. if (pFile == NULL) {
  151. ErrSetErrorCode(ERR_FILE_CREATE, szShutdownFile);
  152. return (ERR_FILE_CREATE);
  153. }
  154. char szShutdownTimeStr[256] = "";
  155. MscGetTimeStr(szShutdownTimeStr, sizeof(szShutdownTimeStr));
  156. fprintf(pFile, "%sn", szShutdownTimeStr);
  157. fclose(pFile);
  158. return (0);
  159. }
  160. static int SvrSetupCTRL(int iArgCount, char *pszArgs[])
  161. {
  162. int iPort = STD_CTRL_PORT;
  163. int iSessionTimeout = CTRL_SERVER_SESSION_TIMEOUT;
  164. int iNumAddr = 0;
  165. long lMaxThreads = MAX_CTRL_THREADS;
  166. unsigned long ulFlags = 0;
  167. SYS_INET_ADDR SvrAddr[MAX_CTRL_ACCEPT_ADDRESSES];
  168. for (int ii = 0; ii < iArgCount; ii++) {
  169. if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'C'))
  170. continue;
  171. switch (pszArgs[ii][2]) {
  172. case ('p'):
  173. if (++ii < iArgCount)
  174. iPort = atoi(pszArgs[ii]);
  175. break;
  176. case ('t'):
  177. if (++ii < iArgCount)
  178. iSessionTimeout = atoi(pszArgs[ii]);
  179. break;
  180. case ('l'):
  181. ulFlags |= CTRLF_LOG_ENABLED;
  182. break;
  183. case ('I'):
  184. if ((++ii < iArgCount) &&
  185.     (MscGetServerAddress(pszArgs[ii], SvrAddr[iNumAddr]) == 0))
  186. ++iNumAddr;
  187. break;
  188. case ('X'):
  189. if (++ii < iArgCount)
  190. lMaxThreads = atol(pszArgs[ii]);
  191. break;
  192. }
  193. }
  194. if ((hShbCTRL = ShbCreateBlock(sizeof(CTRLConfig))) == SHB_INVALID_HANDLE)
  195. return (ErrGetErrorCode());
  196. CTRLConfig *pCTRLCfg = (CTRLConfig *) ShbLock(hShbCTRL);
  197. if (pCTRLCfg == NULL) {
  198. ErrorPush();
  199. ShbCloseBlock(hShbCTRL);
  200. return (ErrorPop());
  201. }
  202. pCTRLCfg->iPort = iPort;
  203. pCTRLCfg->ulFlags = ulFlags;
  204. pCTRLCfg->lThreadCount = 0;
  205. pCTRLCfg->lMaxThreads = lMaxThreads;
  206. pCTRLCfg->iSessionTimeout = iSessionTimeout;
  207. pCTRLCfg->iTimeout = STD_SERVER_TIMEOUT;
  208. pCTRLCfg->iNumAddr = iNumAddr;
  209. for (int nn = 0; nn < iNumAddr; nn++)
  210. pCTRLCfg->SvrAddr[nn] = SvrAddr[nn];
  211. ShbUnlock(hShbCTRL);
  212. if ((hCTRLThread = SysCreateThread(CTRLThreadProc, NULL)) == SYS_INVALID_THREAD) {
  213. ShbCloseBlock(hShbCTRL);
  214. return (ErrGetErrorCode());
  215. }
  216. return (0);
  217. }
  218. static void SvrCleanupCTRL(void)
  219. {
  220. ///////////////////////////////////////////////////////////////////////////////
  221. //  Stop CTRL Thread
  222. ///////////////////////////////////////////////////////////////////////////////
  223. CTRLConfig *pCTRLCfg = (CTRLConfig *) ShbLock(hShbCTRL);
  224. pCTRLCfg->ulFlags |= CTRLF_STOP_SERVER;
  225. ShbUnlock(hShbCTRL);
  226. ///////////////////////////////////////////////////////////////////////////////
  227. //  Wait CTRL
  228. ///////////////////////////////////////////////////////////////////////////////
  229. SysWaitThread(hCTRLThread, SVR_EXIT_WAIT);
  230. ///////////////////////////////////////////////////////////////////////////////
  231. //  Close CTRL Thread
  232. ///////////////////////////////////////////////////////////////////////////////
  233. SysCloseThread(hCTRLThread, 1);
  234. ShbCloseBlock(hShbCTRL);
  235. }
  236. static int SvrSetupFING(int iArgCount, char *pszArgs[])
  237. {
  238. int iPort = STD_FINGER_PORT;
  239. int iNumAddr = 0;
  240. unsigned long ulFlags = 0;
  241. SYS_INET_ADDR SvrAddr[MAX_FING_ACCEPT_ADDRESSES];
  242. for (int ii = 0; ii < iArgCount; ii++) {
  243. if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'F'))
  244. continue;
  245. switch (pszArgs[ii][2]) {
  246. case ('p'):
  247. if (++ii < iArgCount)
  248. iPort = atoi(pszArgs[ii]);
  249. break;
  250. case ('l'):
  251. ulFlags |= FINGF_LOG_ENABLED;
  252. break;
  253. case ('I'):
  254. if ((++ii < iArgCount) &&
  255.     (MscGetServerAddress(pszArgs[ii], SvrAddr[iNumAddr]) == 0))
  256. ++iNumAddr;
  257. break;
  258. }
  259. }
  260. if ((hShbFING = ShbCreateBlock(sizeof(FINGConfig))) == SHB_INVALID_HANDLE)
  261. return (ErrGetErrorCode());
  262. FINGConfig *pFINGCfg = (FINGConfig *) ShbLock(hShbFING);
  263. if (pFINGCfg == NULL) {
  264. ShbCloseBlock(hShbFING);
  265. return (ErrGetErrorCode());
  266. }
  267. pFINGCfg->iPort = iPort;
  268. pFINGCfg->ulFlags = ulFlags;
  269. pFINGCfg->lThreadCount = 0;
  270. pFINGCfg->iTimeout = STD_SERVER_TIMEOUT;
  271. pFINGCfg->iNumAddr = iNumAddr;
  272. for (int nn = 0; nn < iNumAddr; nn++)
  273. pFINGCfg->SvrAddr[nn] = SvrAddr[nn];
  274. ShbUnlock(hShbFING);
  275. if ((hFINGThread = SysCreateThread(FINGThreadProc, NULL)) == SYS_INVALID_THREAD) {
  276. ShbCloseBlock(hShbFING);
  277. return (ErrGetErrorCode());
  278. }
  279. return (0);
  280. }
  281. static void SvrCleanupFING(void)
  282. {
  283. ///////////////////////////////////////////////////////////////////////////////
  284. //  Stop FING Thread
  285. ///////////////////////////////////////////////////////////////////////////////
  286. FINGConfig *pFINGCfg = (FINGConfig *) ShbLock(hShbFING);
  287. pFINGCfg->ulFlags |= FINGF_STOP_SERVER;
  288. ShbUnlock(hShbFING);
  289. ///////////////////////////////////////////////////////////////////////////////
  290. //  Wait FINGER
  291. ///////////////////////////////////////////////////////////////////////////////
  292. SysWaitThread(hFINGThread, SVR_EXIT_WAIT);
  293. ///////////////////////////////////////////////////////////////////////////////
  294. //  Close FINGER Thread
  295. ///////////////////////////////////////////////////////////////////////////////
  296. SysCloseThread(hFINGThread, 1);
  297. ShbCloseBlock(hShbFING);
  298. }
  299. static int SvrSetupPOP3(int iArgCount, char *pszArgs[])
  300. {
  301. int iPort = STD_POP3_PORT;
  302. int iSessionTimeout = STD_SERVER_SESSION_TIMEOUT;
  303. int iBadLoginWait = STD_POP3_BADLOGIN_WAIT;
  304. int iNumAddr = 0;
  305. long lMaxThreads = MAX_POP3_THREADS;
  306. unsigned long ulFlags = 0;
  307. SYS_INET_ADDR SvrAddr[MAX_POP3_ACCEPT_ADDRESSES];
  308. for (int ii = 0; ii < iArgCount; ii++) {
  309. if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'P'))
  310. continue;
  311. switch (pszArgs[ii][2]) {
  312. case ('p'):
  313. if (++ii < iArgCount)
  314. iPort = atoi(pszArgs[ii]);
  315. break;
  316. case ('t'):
  317. if (++ii < iArgCount)
  318. iSessionTimeout = atoi(pszArgs[ii]);
  319. break;
  320. case ('w'):
  321. if (++ii < iArgCount)
  322. iBadLoginWait = atoi(pszArgs[ii]);
  323. break;
  324. case ('l'):
  325. ulFlags |= POP3F_LOG_ENABLED;
  326. break;
  327. case ('h'):
  328. ulFlags |= POP3F_HANG_ON_BADLOGIN;
  329. break;
  330. case ('I'):
  331. if ((++ii < iArgCount) &&
  332.     (MscGetServerAddress(pszArgs[ii], SvrAddr[iNumAddr]) == 0))
  333. ++iNumAddr;
  334. break;
  335. case ('X'):
  336. if (++ii < iArgCount)
  337. lMaxThreads = atol(pszArgs[ii]);
  338. break;
  339. }
  340. }
  341. if ((hShbPOP3 = ShbCreateBlock(sizeof(POP3Config))) == SHB_INVALID_HANDLE)
  342. return (ErrGetErrorCode());
  343. POP3Config *pPOP3Cfg = (POP3Config *) ShbLock(hShbPOP3);
  344. if (pPOP3Cfg == NULL) {
  345. ShbCloseBlock(hShbPOP3);
  346. return (ErrGetErrorCode());
  347. }
  348. pPOP3Cfg->iPort = iPort;
  349. pPOP3Cfg->ulFlags = ulFlags;
  350. pPOP3Cfg->lThreadCount = 0;
  351. pPOP3Cfg->lMaxThreads = lMaxThreads;
  352. pPOP3Cfg->iSessionTimeout = iSessionTimeout;
  353. pPOP3Cfg->iTimeout = STD_SERVER_TIMEOUT;
  354. pPOP3Cfg->iBadLoginWait = iBadLoginWait;
  355. pPOP3Cfg->iNumAddr = iNumAddr;
  356. for (int nn = 0; nn < iNumAddr; nn++)
  357. pPOP3Cfg->SvrAddr[nn] = SvrAddr[nn];
  358. ShbUnlock(hShbPOP3);
  359. ///////////////////////////////////////////////////////////////////////////////
  360. //  Remove POP3 lock files
  361. ///////////////////////////////////////////////////////////////////////////////
  362. UsrClearPop3LocksDir();
  363. if ((hPOP3Thread = SysCreateThread(POP3ThreadProc, NULL)) == SYS_INVALID_THREAD) {
  364. ShbCloseBlock(hShbPOP3);
  365. return (ErrGetErrorCode());
  366. }
  367. return (0);
  368. }
  369. static void SvrCleanupPOP3(void)
  370. {
  371. ///////////////////////////////////////////////////////////////////////////////
  372. //  Stop POP3 Thread
  373. ///////////////////////////////////////////////////////////////////////////////
  374. POP3Config *pPOP3Cfg = (POP3Config *) ShbLock(hShbPOP3);
  375. pPOP3Cfg->ulFlags |= POP3F_STOP_SERVER;
  376. ShbUnlock(hShbPOP3);
  377. ///////////////////////////////////////////////////////////////////////////////
  378. //  Wait POP3 Thread
  379. ///////////////////////////////////////////////////////////////////////////////
  380. SysWaitThread(hPOP3Thread, SVR_EXIT_WAIT);
  381. ///////////////////////////////////////////////////////////////////////////////
  382. //  Close POP3 Thread
  383. ///////////////////////////////////////////////////////////////////////////////
  384. SysCloseThread(hPOP3Thread, 1);
  385. ShbCloseBlock(hShbPOP3);
  386. }
  387. static int SvrSetupSMTP(int iArgCount, char *pszArgs[])
  388. {
  389. int iPort = STD_SMTP_PORT;
  390. int iSessionTimeout = STD_SERVER_SESSION_TIMEOUT;
  391. int iMaxRcpts = STD_SMTP_MAX_RCPTS;
  392. int iNumAddr = 0;
  393. unsigned int uPopAuthExpireTime = STD_POP3AUTH_EXPIRE_TIME;
  394. long lMaxThreads = MAX_SMTP_THREADS;
  395. unsigned long ulFlags = 0;
  396. SYS_INET_ADDR SvrAddr[MAX_SMTP_ACCEPT_ADDRESSES];
  397. for (int ii = 0; ii < iArgCount; ii++) {
  398. if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'S'))
  399. continue;
  400. switch (pszArgs[ii][2]) {
  401. case ('p'):
  402. if (++ii < iArgCount)
  403. iPort = atoi(pszArgs[ii]);
  404. break;
  405. case ('t'):
  406. if (++ii < iArgCount)
  407. iSessionTimeout = atoi(pszArgs[ii]);
  408. break;
  409. case ('l'):
  410. ulFlags |= SMTPF_LOG_ENABLED;
  411. break;
  412. case ('I'):
  413. if ((++ii < iArgCount) &&
  414.     (MscGetServerAddress(pszArgs[ii], SvrAddr[iNumAddr]) == 0))
  415. ++iNumAddr;
  416. break;
  417. case ('X'):
  418. if (++ii < iArgCount)
  419. lMaxThreads = atol(pszArgs[ii]);
  420. break;
  421. case ('r'):
  422. if (++ii < iArgCount)
  423. iMaxRcpts = atoi(pszArgs[ii]);
  424. break;
  425. case ('e'):
  426. if (++ii < iArgCount)
  427. uPopAuthExpireTime = (unsigned int) atol(pszArgs[ii]);
  428. break;
  429. }
  430. }
  431. if ((hShbSMTP = ShbCreateBlock(sizeof(SMTPConfig))) == SHB_INVALID_HANDLE)
  432. return (ErrGetErrorCode());
  433. SMTPConfig *pSMTPCfg = (SMTPConfig *) ShbLock(hShbSMTP);
  434. if (pSMTPCfg == NULL) {
  435. ShbCloseBlock(hShbSMTP);
  436. return (ErrGetErrorCode());
  437. }
  438. pSMTPCfg->iPort = iPort;
  439. pSMTPCfg->ulFlags = ulFlags;
  440. pSMTPCfg->lThreadCount = 0;
  441. pSMTPCfg->lMaxThreads = lMaxThreads;
  442. pSMTPCfg->iSessionTimeout = iSessionTimeout;
  443. pSMTPCfg->iTimeout = STD_SERVER_TIMEOUT;
  444. pSMTPCfg->iMaxRcpts = iMaxRcpts;
  445. pSMTPCfg->uPopAuthExpireTime = uPopAuthExpireTime;
  446. pSMTPCfg->iNumAddr = iNumAddr;
  447. for (int nn = 0; nn < iNumAddr; nn++)
  448. pSMTPCfg->SvrAddr[nn] = SvrAddr[nn];
  449. ShbUnlock(hShbSMTP);
  450. if ((hSMTPThread = SysCreateThread(SMTPThreadProc, NULL)) == SYS_INVALID_THREAD) {
  451. ShbCloseBlock(hShbSMTP);
  452. return (ErrGetErrorCode());
  453. }
  454. return (0);
  455. }
  456. static void SvrCleanupSMTP(void)
  457. {
  458. ///////////////////////////////////////////////////////////////////////////////
  459. //  Stop SMTP Thread
  460. ///////////////////////////////////////////////////////////////////////////////
  461. SMTPConfig *pSMTPCfg = (SMTPConfig *) ShbLock(hShbSMTP);
  462. pSMTPCfg->ulFlags |= SMTPF_STOP_SERVER;
  463. ShbUnlock(hShbSMTP);
  464. ///////////////////////////////////////////////////////////////////////////////
  465. //  Wait SMTP Thread
  466. ///////////////////////////////////////////////////////////////////////////////
  467. SysWaitThread(hSMTPThread, SVR_EXIT_WAIT);
  468. ///////////////////////////////////////////////////////////////////////////////
  469. //  Close SMTP Thread
  470. ///////////////////////////////////////////////////////////////////////////////
  471. SysCloseThread(hSMTPThread, 1);
  472. ShbCloseBlock(hShbSMTP);
  473. }
  474. static int SvrSetupSMAIL(int iArgCount, char *pszArgs[])
  475. {
  476. int ii;
  477. int iRetryTimeout = STD_SMAIL_RETRY_TIMEOUT;
  478. int iRetryIncrRatio = STD_SMAIL_RETRY_INCR_RATIO;
  479. int iMaxRetry = STD_SMAIL_MAX_RETRY;
  480. unsigned long ulFlags = 0;
  481. iNumSMAILThreads = STD_SMAIL_THREADS;
  482. for (ii = 0; ii < iArgCount; ii++) {
  483. if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'Q'))
  484. continue;
  485. switch (pszArgs[ii][2]) {
  486. case ('n'):
  487. if (++ii < iArgCount)
  488. iNumSMAILThreads = atoi(pszArgs[ii]);
  489. iNumSMAILThreads = Min(MAX_SMAIL_THREADS, Max(1, iNumSMAILThreads));
  490. break;
  491. case ('t'):
  492. if (++ii < iArgCount)
  493. iRetryTimeout = atoi(pszArgs[ii]);
  494. break;
  495. case ('i'):
  496. if (++ii < iArgCount)
  497. iRetryIncrRatio = atoi(pszArgs[ii]);
  498. break;
  499. case ('r'):
  500. if (++ii < iArgCount)
  501. iMaxRetry = atoi(pszArgs[ii]);
  502. break;
  503. case ('l'):
  504. ulFlags |= SMAILF_LOG_ENABLED;
  505. break;
  506. case ('T'):
  507. if (++ii < iArgCount)
  508. iFilterTimeout = atoi(pszArgs[ii]);
  509. break;
  510. case ('g'):
  511. bFilterLogEnabled = true;
  512. break;
  513. }
  514. }
  515. if ((hShbSMAIL = ShbCreateBlock(sizeof(SMAILConfig))) == SHB_INVALID_HANDLE)
  516. return (ErrGetErrorCode());
  517. SMAILConfig *pSMAILCfg = (SMAILConfig *) ShbLock(hShbSMAIL);
  518. if (pSMAILCfg == NULL) {
  519. ErrorPush();
  520. ShbCloseBlock(hShbSMAIL);
  521. return (ErrorPop());
  522. }
  523. pSMAILCfg->ulFlags = ulFlags;
  524. pSMAILCfg->lThreadCount = 0;
  525. ShbUnlock(hShbSMAIL);
  526. ///////////////////////////////////////////////////////////////////////////////
  527. //  Initialize queue fs
  528. ///////////////////////////////////////////////////////////////////////////////
  529. char szSpoolDir[SYS_MAX_PATH] = "";
  530. SvrGetSpoolDir(szSpoolDir, sizeof(szSpoolDir));
  531. if ((hSpoolQueue = QueOpen(szSpoolDir, iMaxRetry, iRetryTimeout, iRetryIncrRatio,
  532.    iQueueSplitLevel)) == INVALID_QUEUE_HANDLE) {
  533. ErrorPush();
  534. ShbCloseBlock(hShbSMAIL);
  535. return (ErrorPop());
  536. }
  537. ///////////////////////////////////////////////////////////////////////////////
  538. //  Create mailer threads
  539. ///////////////////////////////////////////////////////////////////////////////
  540. for (ii = 0; ii < iNumSMAILThreads; ii++)
  541. hSMAILThreads[ii] = SysCreateThread(SMAILThreadProc, NULL);
  542. return (0);
  543. }
  544. static void SvrCleanupSMAIL(void)
  545. {
  546. ///////////////////////////////////////////////////////////////////////////////
  547. //  Stop SMAIL Thread ( and unlock threads wait with "SysReleaseSemaphore" )
  548. ///////////////////////////////////////////////////////////////////////////////
  549. SMAILConfig *pSMAILCfg = (SMAILConfig *) ShbLock(hShbSMAIL);
  550. pSMAILCfg->ulFlags |= SMAILF_STOP_SERVER;
  551. ShbUnlock(hShbSMAIL);
  552. ///////////////////////////////////////////////////////////////////////////////
  553. //  Wait SMAIL Threads
  554. ///////////////////////////////////////////////////////////////////////////////
  555. int tt;
  556. for (tt = 0; tt < iNumSMAILThreads; tt++)
  557. SysWaitThread(hSMAILThreads[tt], SVR_EXIT_WAIT);
  558. ///////////////////////////////////////////////////////////////////////////////
  559. //  Close SMAIL Threads
  560. ///////////////////////////////////////////////////////////////////////////////
  561. for (tt = 0; tt < iNumSMAILThreads; tt++)
  562. SysCloseThread(hSMAILThreads[tt], 1);
  563. ShbCloseBlock(hShbSMAIL);
  564. ///////////////////////////////////////////////////////////////////////////////
  565. //  Close the mail queue
  566. ///////////////////////////////////////////////////////////////////////////////
  567. QueClose(hSpoolQueue);
  568. }
  569. static int SvrSetupPSYNC(int iArgCount, char *pszArgs[])
  570. {
  571. int iSyncInterval = STD_PSYNC_INTERVAL;
  572. int iNumSyncThreads = STD_PSYNC_NUM_THREADS;
  573. unsigned long ulFlags = 0;
  574. for (int ii = 0; ii < iArgCount; ii++) {
  575. if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'Y'))
  576. continue;
  577. switch (pszArgs[ii][2]) {
  578. case ('i'):
  579. if (++ii < iArgCount)
  580. iSyncInterval = atoi(pszArgs[ii]);
  581. break;
  582. case ('t'):
  583. if (++ii < iArgCount)
  584. iNumSyncThreads = atoi(pszArgs[ii]);
  585. iNumSyncThreads = Min(MAX_PSYNC_NUM_THREADS, Max(1, iNumSyncThreads));
  586. break;
  587. case ('l'):
  588. ulFlags |= PSYNCF_LOG_ENABLED;
  589. break;
  590. }
  591. }
  592. if ((hSyncSem =
  593.      SysCreateSemaphore(iNumSyncThreads, SYS_DEFAULT_MAXCOUNT)) == SYS_INVALID_SEMAPHORE)
  594. return (ErrGetErrorCode());
  595. if ((hShbPSYNC = ShbCreateBlock(sizeof(PSYNCConfig))) == SHB_INVALID_HANDLE) {
  596. ErrorPush();
  597. SysCloseSemaphore(hSyncSem);
  598. return (ErrorPop());
  599. }
  600. PSYNCConfig *pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC);
  601. if (pPSYNCCfg == NULL) {
  602. ErrorPush();
  603. ShbCloseBlock(hShbPSYNC);
  604. SysCloseSemaphore(hSyncSem);
  605. return (ErrorPop());
  606. }
  607. pPSYNCCfg->ulFlags = ulFlags;
  608. pPSYNCCfg->lThreadCount = 0;
  609. pPSYNCCfg->iTimeout = STD_SERVER_TIMEOUT;
  610. pPSYNCCfg->iSyncInterval = iSyncInterval;
  611. pPSYNCCfg->iNumSyncThreads = iNumSyncThreads;
  612. ShbUnlock(hShbPSYNC);
  613. ///////////////////////////////////////////////////////////////////////////////
  614. //  Remove POP3 links lock files
  615. ///////////////////////////////////////////////////////////////////////////////
  616. GwLkClearLinkLocksDir();
  617. if ((hPSYNCThread = SysCreateThread(PSYNCThreadProc, NULL)) == SYS_INVALID_THREAD) {
  618. ShbCloseBlock(hShbPSYNC);
  619. SysCloseSemaphore(hSyncSem);
  620. return (ErrGetErrorCode());
  621. }
  622. return (0);
  623. }
  624. static void SvrCleanupPSYNC(void)
  625. {
  626. ///////////////////////////////////////////////////////////////////////////////
  627. //  Stop PSYNC Thread
  628. ///////////////////////////////////////////////////////////////////////////////
  629. PSYNCConfig *pPSYNCCfg = (PSYNCConfig *) ShbLock(hShbPSYNC);
  630. pPSYNCCfg->ulFlags |= PSYNCF_STOP_SERVER;
  631. ShbUnlock(hShbPSYNC);
  632. ///////////////////////////////////////////////////////////////////////////////
  633. //  Wait PSYNC Thread
  634. ///////////////////////////////////////////////////////////////////////////////
  635. SysWaitThread(hPSYNCThread, SVR_EXIT_WAIT);
  636. ///////////////////////////////////////////////////////////////////////////////
  637. //  Close PSYNC Thread
  638. ///////////////////////////////////////////////////////////////////////////////
  639. SysCloseThread(hPSYNCThread, 1);
  640. ShbCloseBlock(hShbPSYNC);
  641. SysCloseSemaphore(hSyncSem);
  642. }
  643. static int SvrSetupLMAIL(int iArgCount, char *pszArgs[])
  644. {
  645. int ii;
  646. int iSleepTimeout = STD_LMAILTHREAD_SLEEP_TIME;
  647. unsigned long ulFlags = 0;
  648. iNumLMAILThreads = STD_LMAIL_THREADS;
  649. for (ii = 0; ii < iArgCount; ii++) {
  650. if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'L'))
  651. continue;
  652. switch (pszArgs[ii][2]) {
  653. case ('n'):
  654. if (++ii < iArgCount)
  655. iNumLMAILThreads = atoi(pszArgs[ii]);
  656. iNumLMAILThreads = Min(MAX_LMAIL_THREADS, Max(1, iNumLMAILThreads));
  657. break;
  658. case ('l'):
  659. ulFlags |= LMAILF_LOG_ENABLED;
  660. break;
  661. case ('t'):
  662. if (++ii < iArgCount)
  663. iSleepTimeout = atoi(pszArgs[ii]);
  664. break;
  665. }
  666. }
  667. if ((hShbLMAIL = ShbCreateBlock(sizeof(LMAILConfig))) == SHB_INVALID_HANDLE)
  668. return (ErrGetErrorCode());
  669. LMAILConfig *pLMAILCfg = (LMAILConfig *) ShbLock(hShbLMAIL);
  670. if (pLMAILCfg == NULL) {
  671. ErrorPush();
  672. ShbCloseBlock(hShbLMAIL);
  673. return (ErrorPop());
  674. }
  675. pLMAILCfg->ulFlags = ulFlags;
  676. pLMAILCfg->iSleepTimeout = iSleepTimeout;
  677. pLMAILCfg->lNumThreads = iNumLMAILThreads;
  678. pLMAILCfg->lThreadCount = 0;
  679. ShbUnlock(hShbLMAIL);
  680. ///////////////////////////////////////////////////////////////////////////////
  681. //  Create mailer threads
  682. ///////////////////////////////////////////////////////////////////////////////
  683. for (ii = 0; ii < iNumLMAILThreads; ii++)
  684. hLMAILThreads[ii] = SysCreateThread(LMAILThreadProc, NULL);
  685. return (0);
  686. }
  687. static void SvrCleanupLMAIL(void)
  688. {
  689. ///////////////////////////////////////////////////////////////////////////////
  690. //  Stop LMAIL Thread ( and unlock threads wait with "SysReleaseSemaphore" )
  691. ///////////////////////////////////////////////////////////////////////////////
  692. LMAILConfig *pLMAILCfg = (LMAILConfig *) ShbLock(hShbLMAIL);
  693. pLMAILCfg->ulFlags |= LMAILF_STOP_SERVER;
  694. ShbUnlock(hShbLMAIL);
  695. ///////////////////////////////////////////////////////////////////////////////
  696. //  Wait LMAIL Threads
  697. ///////////////////////////////////////////////////////////////////////////////
  698. int tt;
  699. for (tt = 0; tt < iNumLMAILThreads; tt++)
  700. SysWaitThread(hLMAILThreads[tt], SVR_EXIT_WAIT);
  701. ///////////////////////////////////////////////////////////////////////////////
  702. //  Close LMAIL Threads
  703. ///////////////////////////////////////////////////////////////////////////////
  704. for (tt = 0; tt < iNumLMAILThreads; tt++)
  705. SysCloseThread(hLMAILThreads[tt], 1);
  706. ShbCloseBlock(hShbLMAIL);
  707. }
  708. static int SvrSetup(int iArgCount, char *pszArgs[])
  709. {
  710. StrSNCpy(szMailPath, SYS_BASE_FS_STR);
  711. char *pszValue = SysGetEnv(ENV_MAIN_PATH);
  712. if (pszValue != NULL) {
  713. if (strncmp(szMailPath, pszValue, strlen(szMailPath)) == 0)
  714. StrSNCpy(szMailPath, pszValue);
  715. else
  716. StrSNCat(szMailPath, pszValue);
  717. DelFinalSlash(szMailPath);
  718. SysFree(pszValue);
  719. }
  720. bServerDebug = false;
  721. int iSndBufSize = -1;
  722. int iRcvBufSize = -1;
  723. int iDnsCacheDirs = DNS_HASH_NUM_DIRS;
  724. for (int ii = 0; ii < iArgCount; ii++) {
  725. if ((pszArgs[ii][0] != '-') || (pszArgs[ii][1] != 'M'))
  726. continue;
  727. switch (pszArgs[ii][2]) {
  728. case ('s'):
  729. if (++ii < iArgCount) {
  730. StrSNCpy(szMailPath, pszArgs[ii]);
  731. DelFinalSlash(szMailPath);
  732. }
  733. break;
  734. case ('d'):
  735. bServerDebug = true;
  736. break;
  737. case ('r'):
  738. if (++ii < iArgCount)
  739. iLogRotateHours = atoi(pszArgs[ii]);
  740. break;
  741. case ('x'):
  742. if (++ii < iArgCount) {
  743. iQueueSplitLevel = atoi(pszArgs[ii]);
  744. while (!IsPrimeNumber(iQueueSplitLevel))
  745. ++iQueueSplitLevel;
  746. }
  747. break;
  748. case ('R'):
  749. if (++ii < iArgCount) {
  750. iRcvBufSize = atoi(pszArgs[ii]);
  751. iRcvBufSize = NbrCeil(iRcvBufSize, 1024);
  752. }
  753. break;
  754. case ('S'):
  755. if (++ii < iArgCount) {
  756. iSndBufSize = atoi(pszArgs[ii]);
  757. iSndBufSize = NbrCeil(iSndBufSize, 1024);
  758. }
  759. break;
  760. case ('M'):
  761. iMailboxType = XMAIL_MAILDIR;
  762. break;
  763. case ('m'):
  764. iMailboxType = XMAIL_MAILBOX;
  765. break;
  766. case ('D'):
  767. if (++ii < iArgCount)
  768. iDnsCacheDirs = atoi(pszArgs[ii]);
  769. break;
  770. }
  771. }
  772. if ((strlen(szMailPath) == 0) || !SysExistDir(szMailPath)) {
  773. ErrSetErrorCode(ERR_CONF_PATH);
  774. return (ERR_CONF_PATH);
  775. }
  776. AppendSlash(szMailPath);
  777. ///////////////////////////////////////////////////////////////////////////////
  778. //  Setup library socket buffers
  779. ///////////////////////////////////////////////////////////////////////////////
  780. SysSetupSocketBuffers((iSndBufSize > 0) ? &iSndBufSize : NULL,
  781.       (iRcvBufSize > 0) ? &iRcvBufSize : NULL);
  782. ///////////////////////////////////////////////////////////////////////////////
  783. //  Setup shutdown file name ( must be called before any shutdown function )
  784. ///////////////////////////////////////////////////////////////////////////////
  785. sprintf(szShutdownFile, "%s%s", szMailPath, SVR_SHUTDOWN_FILE);
  786. ///////////////////////////////////////////////////////////////////////////////
  787. //  Setup resource lockers
  788. ///////////////////////////////////////////////////////////////////////////////
  789. if (RLckInitLockers() < 0)
  790. return (ErrGetErrorCode());
  791. ///////////////////////////////////////////////////////////////////////////////
  792. //  Check dynamic DNS setup
  793. ///////////////////////////////////////////////////////////////////////////////
  794. if (DynDnsSetup() < 0) {
  795. ErrorPush();
  796. RLckCleanupLockers();
  797. return (ErrorPop());
  798. }
  799. ///////////////////////////////////////////////////////////////////////////////
  800. //  Clear shutdown condition
  801. ///////////////////////////////////////////////////////////////////////////////
  802. SvrShutdownCleanup();
  803. ///////////////////////////////////////////////////////////////////////////////
  804. //  Align table indexes
  805. ///////////////////////////////////////////////////////////////////////////////
  806. if ((UsrCheckUsersIndexes() < 0) ||
  807.     (UsrCheckAliasesIndexes() < 0) ||
  808.     (ExAlCheckAliasIndexes() < 0) ||
  809.     (MDomCheckDomainsIndexes() < 0) || (ADomCheckDomainsIndexes() < 0)) {
  810. ErrorPush();
  811. RLckCleanupLockers();
  812. return (ErrorPop());
  813. }
  814. ///////////////////////////////////////////////////////////////////////////////
  815. //  Initialize DNS cache
  816. ///////////////////////////////////////////////////////////////////////////////
  817. if (CDNS_Initialize(iDnsCacheDirs) < 0) {
  818. ErrorPush();
  819. RLckCleanupLockers();
  820. return (ErrorPop());
  821. }
  822. return (0);
  823. }
  824. static void SvrCleanup(void)
  825. {
  826. ///////////////////////////////////////////////////////////////////////////////
  827. //  Cleanup resource lockers
  828. ///////////////////////////////////////////////////////////////////////////////
  829. RLckCleanupLockers();
  830. ///////////////////////////////////////////////////////////////////////////////
  831. //  Clear shutdown condition
  832. ///////////////////////////////////////////////////////////////////////////////
  833. SvrShutdownCleanup();
  834. }
  835. static void SvrBreakHandler(void)
  836. {
  837. ///////////////////////////////////////////////////////////////////////////////
  838. //  Set shutdown condition
  839. ///////////////////////////////////////////////////////////////////////////////
  840. SvrSetShutdown();
  841. }
  842. static char **SvrMergeArgs(int iArgs, char *pszArgs[], int &iArgsCount)
  843. {
  844. int iCmdArgs = 0;
  845. char **ppszCmdArgs = NULL;
  846. char *pszCmdLine = SysGetEnv(ENV_CMD_LINE);
  847. if (pszCmdLine != NULL) {
  848. ppszCmdArgs = StrGetArgs(pszCmdLine, iCmdArgs);
  849. SysFree(pszCmdLine);
  850. }
  851. char **ppszMergeArgs = (char **) SysAlloc((iCmdArgs + iArgs + 1) * sizeof(char *));
  852. if (ppszMergeArgs == NULL) {
  853. if (ppszCmdArgs != NULL)
  854. StrFreeStrings(ppszCmdArgs);
  855. return (NULL);
  856. }
  857. iArgsCount = 0;
  858. for (int ii = 0; ii < iArgs; ii++, iArgsCount++)
  859. ppszMergeArgs[iArgsCount] = SysStrDup(pszArgs[ii]);
  860. for (int jj = 0; jj < iCmdArgs; jj++, iArgsCount++)
  861. ppszMergeArgs[iArgsCount] = SysStrDup(ppszCmdArgs[jj]);
  862. ppszMergeArgs[iArgsCount] = NULL;
  863. if (ppszCmdArgs != NULL)
  864. StrFreeStrings(ppszCmdArgs);
  865. return (ppszMergeArgs);
  866. }
  867. int SvrMain(int iArgCount, char *pszArgs[])
  868. {
  869. if (SysInitLibrary() < 0) {
  870. ErrorPush();
  871. SysEventLog(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  872. return (ErrorPop());
  873. }
  874. int iMergeArgsCount = 0;
  875. char **ppszMergeArgs = SvrMergeArgs(iArgCount, pszArgs, iMergeArgsCount);
  876. if (ppszMergeArgs == NULL) {
  877. ErrorPush();
  878. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  879. SysCleanupLibrary();
  880. return (ErrorPop());
  881. }
  882. if (SvrSetup(iMergeArgsCount, ppszMergeArgs) < 0) {
  883. ErrorPush();
  884. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  885. StrFreeStrings(ppszMergeArgs);
  886. SysCleanupLibrary();
  887. return (ErrorPop());
  888. }
  889. if (SvrSetupSMAIL(iMergeArgsCount, ppszMergeArgs) < 0) {
  890. ErrorPush();
  891. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  892. StrFreeStrings(ppszMergeArgs);
  893. SvrCleanup();
  894. SysCleanupLibrary();
  895. return (ErrorPop());
  896. }
  897. if (SvrSetupCTRL(iMergeArgsCount, ppszMergeArgs) < 0) {
  898. ErrorPush();
  899. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  900. SvrCleanupSMAIL();
  901. StrFreeStrings(ppszMergeArgs);
  902. SvrCleanup();
  903. SysCleanupLibrary();
  904. return (ErrorPop());
  905. }
  906. if (SvrSetupPOP3(iMergeArgsCount, ppszMergeArgs) < 0) {
  907. ErrorPush();
  908. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  909. SvrCleanupCTRL();
  910. SvrCleanupSMAIL();
  911. StrFreeStrings(ppszMergeArgs);
  912. SvrCleanup();
  913. SysCleanupLibrary();
  914. return (ErrorPop());
  915. }
  916. if (SvrSetupSMTP(iMergeArgsCount, ppszMergeArgs) < 0) {
  917. ErrorPush();
  918. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  919. SvrCleanupPOP3();
  920. SvrCleanupCTRL();
  921. SvrCleanupSMAIL();
  922. StrFreeStrings(ppszMergeArgs);
  923. SvrCleanup();
  924. SysCleanupLibrary();
  925. return (ErrorPop());
  926. }
  927. if (SvrSetupPSYNC(iMergeArgsCount, ppszMergeArgs) < 0) {
  928. ErrorPush();
  929. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  930. SvrCleanupSMTP();
  931. SvrCleanupPOP3();
  932. SvrCleanupCTRL();
  933. SvrCleanupSMAIL();
  934. StrFreeStrings(ppszMergeArgs);
  935. SvrCleanup();
  936. SysCleanupLibrary();
  937. return (ErrorPop());
  938. }
  939. if (SvrSetupFING(iMergeArgsCount, ppszMergeArgs) < 0) {
  940. ErrorPush();
  941. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  942. SvrCleanupPSYNC();
  943. SvrCleanupSMTP();
  944. SvrCleanupPOP3();
  945. SvrCleanupCTRL();
  946. SvrCleanupSMAIL();
  947. StrFreeStrings(ppszMergeArgs);
  948. SvrCleanup();
  949. SysCleanupLibrary();
  950. return (ErrorPop());
  951. }
  952. if (SvrSetupLMAIL(iMergeArgsCount, ppszMergeArgs) < 0) {
  953. ErrorPush();
  954. SysLogMessage(LOG_LEV_ERROR, "%sn", ErrGetErrorString());
  955. SvrCleanupFING();
  956. SvrCleanupPSYNC();
  957. SvrCleanupSMTP();
  958. SvrCleanupPOP3();
  959. SvrCleanupCTRL();
  960. SvrCleanupSMAIL();
  961. StrFreeStrings(ppszMergeArgs);
  962. SvrCleanup();
  963. SysCleanupLibrary();
  964. return (ErrorPop());
  965. }
  966. StrFreeStrings(ppszMergeArgs);
  967. ///////////////////////////////////////////////////////////////////////////////
  968. //  Set stop handler
  969. ///////////////////////////////////////////////////////////////////////////////
  970. SysSetBreakHandler(SvrBreakHandler);
  971. ///////////////////////////////////////////////////////////////////////////////
  972. //  Server main loop
  973. ///////////////////////////////////////////////////////////////////////////////
  974. for (; !SvrInShutdown(true);) {
  975. SysSleep(SERVER_SLEEP_TIMESLICE);
  976. }
  977. ///////////////////////////////////////////////////////////////////////////////
  978. //  Goodbye cleanups
  979. ///////////////////////////////////////////////////////////////////////////////
  980. SvrCleanupLMAIL();
  981. SvrCleanupFING();
  982. SvrCleanupPSYNC();
  983. SvrCleanupSMTP();
  984. SvrCleanupPOP3();
  985. SvrCleanupCTRL();
  986. SvrCleanupSMAIL();
  987. SvrCleanup();
  988. SysLogMessage(LOG_LEV_MESSAGE, APP_NAME_VERSION_STR " server stoppedn");
  989. SysCleanupLibrary();
  990. return (0);
  991. }
  992. int SvrStopServer(bool bWait)
  993. {
  994. ///////////////////////////////////////////////////////////////////////////////
  995. //  Set shutdown condition
  996. ///////////////////////////////////////////////////////////////////////////////
  997. SvrSetShutdown();
  998. if (bWait) {
  999. int iWaitTime = 0;
  1000. for (; SvrInShutdown(true); iWaitTime += SERVER_SLEEP_TIMESLICE)
  1001. SysSleep(SERVER_SLEEP_TIMESLICE);
  1002. }
  1003. return (0);
  1004. }
  1005. bool SvrInShutdown(bool bForceCheck)
  1006. {
  1007. time_t tNow = time(NULL);
  1008. static time_t tLastCheck = 0;
  1009. static bool bShutdown = false;
  1010. if (bForceCheck || (tNow > (tLastCheck + SHUTDOWN_CHECK_TIME))) {
  1011. tLastCheck = tNow;
  1012. if (bServerShutdown)
  1013. bShutdown = true;
  1014. else if (SysExistFile(szShutdownFile)) {
  1015. bServerShutdown = true;
  1016. SysShutdownLibrary();
  1017. bShutdown = true;
  1018. }
  1019. }
  1020. return (bShutdown);
  1021. }