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

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 "ShBlocks.h"
  26. #include "ResLocks.h"
  27. #include "StrUtils.h"
  28. #include "SList.h"
  29. #include "BuffSock.h"
  30. #include "MailConfig.h"
  31. #include "UsrUtils.h"
  32. #include "SvrUtils.h"
  33. #include "MessQueue.h"
  34. #include "SMAILUtils.h"
  35. #include "QueueUtils.h"
  36. #include "SMAILSvr.h"
  37. #include "AppDefines.h"
  38. #include "MailSvr.h"
  39. #include "MiscUtils.h"
  40. #define SVR_PROFILE_FILE            "server.tab"
  41. #define MESSAGEID_FILE              "message.id"
  42. #define SMTP_SPOOL_DIR              "spool"
  43. #define MAX_MSG_FILENAME_LENGTH     80
  44. #define SVR_PROFILE_LINE_MAX        2048
  45. #define SYS_RES_CHECK_INTERVAL      8
  46. struct ServerInfoVar {
  47. LISTLINK LL;
  48. char *pszName;
  49. char *pszValue;
  50. };
  51. struct ServerConfigData {
  52. RLCK_HANDLE hResLock;
  53. int iWriteLock;
  54. HSLIST hConfigList;
  55. };
  56. static char *SvrGetProfileFilePath(char *pszFilePath, int iMaxPath);
  57. static ServerInfoVar *SvrAllocVar(const char *pszName, const char *pszValue);
  58. static void SvrFreeVar(ServerInfoVar * pSIV);
  59. static void SvrFreeInfoList(HSLIST & hConfigList);
  60. static ServerInfoVar *SvrGetUserVar(HSLIST & hConfigList, const char *pszName);
  61. static int SvrWriteInfoList(HSLIST & hConfigList, FILE * pProfileFile);
  62. static int SvrLoadServerConfig(HSLIST & hConfigList, const char *pszFilePath);
  63. static char *SvrGetProfileFilePath(char *pszFilePath, int iMaxPath)
  64. {
  65. CfgGetRootPath(pszFilePath, iMaxPath);
  66. StrNCat(pszFilePath, SVR_PROFILE_FILE, iMaxPath);
  67. return (pszFilePath);
  68. }
  69. SVRCFG_HANDLE SvrGetConfigHandle(int iWriteLock)
  70. {
  71. char szProfilePath[SYS_MAX_PATH] = "";
  72. SvrGetProfileFilePath(szProfilePath, sizeof(szProfilePath));
  73. ///////////////////////////////////////////////////////////////////////////////
  74. //  Lock the profile resource
  75. ///////////////////////////////////////////////////////////////////////////////
  76. RLCK_HANDLE hResLock = INVALID_RLCK_HANDLE;
  77. char szResLock[SYS_MAX_PATH] = "";
  78. if (iWriteLock) {
  79. if ((hResLock = RLckLockEX(CfgGetBasedPath(szProfilePath, szResLock,
  80.    sizeof(szResLock)))) ==
  81.     INVALID_RLCK_HANDLE)
  82. return (INVALID_SVRCFG_HANDLE);
  83. } else {
  84. if ((hResLock = RLckLockSH(CfgGetBasedPath(szProfilePath, szResLock,
  85.    sizeof(szResLock)))) ==
  86.     INVALID_RLCK_HANDLE)
  87. return (INVALID_SVRCFG_HANDLE);
  88. }
  89. ServerConfigData *pSCD = (ServerConfigData *) SysAlloc(sizeof(ServerConfigData));
  90. if (pSCD == NULL) {
  91. if (iWriteLock)
  92. RLckUnlockEX(hResLock);
  93. else
  94. RLckUnlockSH(hResLock);
  95. return (INVALID_SVRCFG_HANDLE);
  96. }
  97. pSCD->hResLock = hResLock;
  98. pSCD->iWriteLock = iWriteLock;
  99. ListInit(pSCD->hConfigList);
  100. if (SvrLoadServerConfig(pSCD->hConfigList, szProfilePath) < 0) {
  101. if (iWriteLock)
  102. RLckUnlockEX(hResLock);
  103. else
  104. RLckUnlockSH(hResLock);
  105. SysFree(pSCD);
  106. return (INVALID_SVRCFG_HANDLE);
  107. }
  108. return ((SVRCFG_HANDLE) pSCD);
  109. }
  110. void SvrReleaseConfigHandle(SVRCFG_HANDLE hSvrConfig)
  111. {
  112. ServerConfigData *pSCD = (ServerConfigData *) hSvrConfig;
  113. ///////////////////////////////////////////////////////////////////////////////
  114. //  Unlock the profile resource
  115. ///////////////////////////////////////////////////////////////////////////////
  116. if (pSCD->iWriteLock)
  117. RLckUnlockEX(pSCD->hResLock);
  118. else
  119. RLckUnlockSH(pSCD->hResLock);
  120. SvrFreeInfoList(pSCD->hConfigList);
  121. SysFree(pSCD);
  122. }
  123. char *SvrGetConfigVar(SVRCFG_HANDLE hSvrConfig, const char *pszName, const char *pszDefault)
  124. {
  125. ServerConfigData *pSCD = (ServerConfigData *) hSvrConfig;
  126. ServerInfoVar *pSIV = SvrGetUserVar(pSCD->hConfigList, pszName);
  127. if (pSIV != NULL)
  128. return (SysStrDup(pSIV->pszValue));
  129. return ((pszDefault != NULL) ? SysStrDup(pszDefault) : NULL);
  130. }
  131. bool SvrTestConfigFlag(char const *pszName, bool bDefault, SVRCFG_HANDLE hSvrConfig)
  132. {
  133. char szValue[64] = "";
  134. SvrConfigVar(pszName, szValue, sizeof(szValue) - 1, hSvrConfig, (bDefault) ? "1" : "0");
  135. return ((atoi(szValue) != 0) ? true : false);
  136. }
  137. int SvrGetConfigInt(char const *pszName, int iDefault, SVRCFG_HANDLE hSvrConfig)
  138. {
  139. char szValue[64] = "";
  140. return (((SvrConfigVar(pszName, szValue, sizeof(szValue) - 1, hSvrConfig, NULL) < 0) ||
  141.  IsEmptyString(szValue)) ? iDefault : atoi(szValue));
  142. }
  143. int SysFlushConfig(SVRCFG_HANDLE hSvrConfig)
  144. {
  145. ServerConfigData *pSCD = (ServerConfigData *) hSvrConfig;
  146. if (!pSCD->iWriteLock) {
  147. ErrSetErrorCode(ERR_SVR_PRFILE_NOT_LOCKED);
  148. return (ERR_SVR_PRFILE_NOT_LOCKED);
  149. }
  150. char szProfilePath[SYS_MAX_PATH] = "";
  151. SvrGetProfileFilePath(szProfilePath, sizeof(szProfilePath));
  152. char szResLock[SYS_MAX_PATH] = "";
  153. RLCK_HANDLE hResLock = RLckLockEX(CfgGetBasedPath(szProfilePath, szResLock,
  154.   sizeof(szResLock)));
  155. if (hResLock == INVALID_RLCK_HANDLE)
  156. return (ErrGetErrorCode());
  157. FILE *pProfileFile = fopen(szProfilePath, "wt");
  158. if (pProfileFile == NULL) {
  159. RLckUnlockEX(hResLock);
  160. ErrSetErrorCode(ERR_FILE_CREATE);
  161. return (ERR_FILE_CREATE);
  162. }
  163. int iFlushResult = SvrWriteInfoList(pSCD->hConfigList, pProfileFile);
  164. fclose(pProfileFile);
  165. RLckUnlockEX(hResLock);
  166. return (iFlushResult);
  167. }
  168. static ServerInfoVar *SvrAllocVar(const char *pszName, const char *pszValue)
  169. {
  170. ServerInfoVar *pSIV = (ServerInfoVar *) SysAlloc(sizeof(ServerInfoVar));
  171. if (pSIV == NULL)
  172. return (NULL);
  173. ListLinkInit(pSIV);
  174. pSIV->pszName = SysStrDup(pszName);
  175. pSIV->pszValue = SysStrDup(pszValue);
  176. return (pSIV);
  177. }
  178. static void SvrFreeVar(ServerInfoVar * pSIV)
  179. {
  180. SysFree(pSIV->pszName);
  181. SysFree(pSIV->pszValue);
  182. SysFree(pSIV);
  183. }
  184. static void SvrFreeInfoList(HSLIST & hConfigList)
  185. {
  186. ServerInfoVar *pSIV;
  187. while ((pSIV = (ServerInfoVar *) ListRemove(hConfigList)) != INVALID_SLIST_PTR)
  188. SvrFreeVar(pSIV);
  189. }
  190. static ServerInfoVar *SvrGetUserVar(HSLIST & hConfigList, const char *pszName)
  191. {
  192. ServerInfoVar *pSIV = (ServerInfoVar *) ListFirst(hConfigList);
  193. for (; pSIV != INVALID_SLIST_PTR; pSIV = (ServerInfoVar *)
  194.      ListNext(hConfigList, (PLISTLINK) pSIV))
  195. if (strcmp(pSIV->pszName, pszName) == 0)
  196. return (pSIV);
  197. return (NULL);
  198. }
  199. static int SvrWriteInfoList(HSLIST & hConfigList, FILE * pProfileFile)
  200. {
  201. ServerInfoVar *pSIV = (ServerInfoVar *) ListFirst(hConfigList);
  202. for (; pSIV != INVALID_SLIST_PTR; pSIV = (ServerInfoVar *)
  203.      ListNext(hConfigList, (PLISTLINK) pSIV)) {
  204. ///////////////////////////////////////////////////////////////////////////////
  205. //  Write variabile name
  206. ///////////////////////////////////////////////////////////////////////////////
  207. char *pszQuoted = StrQuote(pSIV->pszName, '"');
  208. if (pszQuoted == NULL)
  209. return (ErrGetErrorCode());
  210. fprintf(pProfileFile, "%st", pszQuoted);
  211. SysFree(pszQuoted);
  212. ///////////////////////////////////////////////////////////////////////////////
  213. //  Write variabile value
  214. ///////////////////////////////////////////////////////////////////////////////
  215. pszQuoted = StrQuote(pSIV->pszValue, '"');
  216. if (pszQuoted == NULL)
  217. return (ErrGetErrorCode());
  218. fprintf(pProfileFile, "%sn", pszQuoted);
  219. SysFree(pszQuoted);
  220. }
  221. return (0);
  222. }
  223. static int SvrLoadServerConfig(HSLIST & hConfigList, const char *pszFilePath)
  224. {
  225. char szResLock[SYS_MAX_PATH] = "";
  226. RLCK_HANDLE hResLock = RLckLockSH(CfgGetBasedPath(pszFilePath, szResLock,
  227.   sizeof(szResLock)));
  228. if (hResLock == INVALID_RLCK_HANDLE)
  229. return (ErrGetErrorCode());
  230. FILE *pProfileFile = fopen(pszFilePath, "rt");
  231. if (pProfileFile == NULL) {
  232. RLckUnlockSH(hResLock);
  233. ErrSetErrorCode(ERR_NO_USER_PRFILE);
  234. return (ERR_NO_USER_PRFILE);
  235. }
  236. char szProfileLine[SVR_PROFILE_LINE_MAX] = "";
  237. while (MscGetConfigLine(szProfileLine, sizeof(szProfileLine) - 1, pProfileFile) != NULL) {
  238. char **ppszStrings = StrGetTabLineStrings(szProfileLine);
  239. if (ppszStrings == NULL)
  240. continue;
  241. int iFieldsCount = StrStringsCount(ppszStrings);
  242. if (iFieldsCount == 2) {
  243. ServerInfoVar *pSIV = SvrAllocVar(ppszStrings[0], ppszStrings[1]);
  244. if (pSIV != NULL)
  245. ListAddTail(hConfigList, (PLISTLINK) pSIV);
  246. }
  247. StrFreeStrings(ppszStrings);
  248. }
  249. fclose(pProfileFile);
  250. RLckUnlockSH(hResLock);
  251. return (0);
  252. }
  253. int SvrGetMessageID(SYS_UINT64 * pullMessageID)
  254. {
  255. char szMsgIDFile[SYS_MAX_PATH] = "";
  256. CfgGetRootPath(szMsgIDFile, sizeof(szMsgIDFile));
  257. StrNCat(szMsgIDFile, MESSAGEID_FILE, sizeof(szMsgIDFile));
  258. char szResLock[SYS_MAX_PATH] = "";
  259. RLCK_HANDLE hResLock = RLckLockEX(CfgGetBasedPath(szMsgIDFile, szResLock,
  260.   sizeof(szResLock)));
  261. if (hResLock == INVALID_RLCK_HANDLE)
  262. return (ErrGetErrorCode());
  263. FILE *pMsgIDFile = fopen(szMsgIDFile, "r+b");
  264. if (pMsgIDFile == NULL) {
  265. if ((pMsgIDFile = fopen(szMsgIDFile, "wb")) == NULL) {
  266. RLckUnlockEX(hResLock);
  267. ErrSetErrorCode(ERR_FILE_CREATE, szMsgIDFile);
  268. return (ERR_FILE_CREATE);
  269. }
  270. *pullMessageID = 1;
  271. } else {
  272. char szMessageID[128] = "";
  273. if ((MscGetString(pMsgIDFile, szMessageID, sizeof(szMessageID) - 1) == NULL) ||
  274.     !isdigit(szMessageID[0])) {
  275. fclose(pMsgIDFile);
  276. RLckUnlockEX(hResLock);
  277. ErrSetErrorCode(ERR_INVALID_FILE, szMsgIDFile);
  278. return (ERR_INVALID_FILE);
  279. }
  280. if (sscanf(szMessageID, SYS_LLU_FMT, pullMessageID) != 1) {
  281. fclose(pMsgIDFile);
  282. RLckUnlockEX(hResLock);
  283. ErrSetErrorCode(ERR_INVALID_FILE, szMsgIDFile);
  284. return (ERR_INVALID_FILE);
  285. }
  286. }
  287. ++*pullMessageID;
  288. fseek(pMsgIDFile, 0, SEEK_SET);
  289. fprintf(pMsgIDFile, SYS_LLU_FMT "rn", *pullMessageID);
  290. fclose(pMsgIDFile);
  291. RLckUnlockEX(hResLock);
  292. return (0);
  293. }
  294. char *SvrGetLogsDir(char *pszLogsPath, int iMaxPath)
  295. {
  296. CfgGetRootPath(pszLogsPath, iMaxPath);
  297. StrNCat(pszLogsPath, SVR_LOGS_DIR, iMaxPath);
  298. return (pszLogsPath);
  299. }
  300. char *SvrGetSpoolDir(char *pszSpoolPath, int iMaxPath)
  301. {
  302. CfgGetRootPath(pszSpoolPath, iMaxPath);
  303. StrNCat(pszSpoolPath, SMTP_SPOOL_DIR, iMaxPath);
  304. return (pszSpoolPath);
  305. }
  306. int SvrConfigVar(char const *pszVarName, char *pszVarValue, int iMaxVarValue,
  307.  SVRCFG_HANDLE hSvrConfig, char const *pszDefault)
  308. {
  309. int iReleaseConfig = 0;
  310. if (hSvrConfig == INVALID_SVRCFG_HANDLE) {
  311. if ((hSvrConfig = SvrGetConfigHandle()) == INVALID_SVRCFG_HANDLE)
  312. return (ErrGetErrorCode());
  313. ++iReleaseConfig;
  314. }
  315. char *pszValue = SvrGetConfigVar(hSvrConfig, pszVarName, pszDefault);
  316. if (pszValue == NULL) {
  317. if (iReleaseConfig)
  318. SvrReleaseConfigHandle(hSvrConfig);
  319. ErrSetErrorCode(ERR_CFG_VAR_NOT_FOUND);
  320. return (ERR_CFG_VAR_NOT_FOUND);
  321. }
  322. strncpy(pszVarValue, pszValue, iMaxVarValue - 1);
  323. pszVarValue[iMaxVarValue - 1] = '';
  324. SysFree(pszValue);
  325. if (iReleaseConfig)
  326. SvrReleaseConfigHandle(hSvrConfig);
  327. return (0);
  328. }
  329. int SvrCheckDiskSpace(unsigned long ulMinSpace)
  330. {
  331. time_t tNow = time(NULL);
  332. static SYS_INT64 FreeSpace = 0;
  333. static time_t tLastCheck = 0;
  334. if (tNow > (tLastCheck + SYS_RES_CHECK_INTERVAL)) {
  335. SYS_INT64 TotalSpace;
  336. char szRootDir[SYS_MAX_PATH] = "";
  337. tLastCheck = tNow;
  338. CfgGetRootPath(szRootDir, sizeof(szRootDir));
  339. if (SysGetDiskSpace(szRootDir, &TotalSpace, &FreeSpace) < 0)
  340. return (ErrGetErrorCode());
  341. }
  342. if (FreeSpace < (SYS_INT64) ulMinSpace) {
  343. ErrSetErrorCode(ERR_LOW_DISK_SPACE);
  344. return (ERR_LOW_DISK_SPACE);
  345. }
  346. return (0);
  347. }
  348. int SvrCheckVirtMemSpace(unsigned long ulMinSpace)
  349. {
  350. time_t tNow = time(NULL);
  351. static SYS_INT64 FreeSpace = 0;
  352. static time_t tLastCheck = 0;
  353. if (tNow > (tLastCheck + SYS_RES_CHECK_INTERVAL)) {
  354. tLastCheck = tNow;
  355. SYS_INT64 RamTotal;
  356. SYS_INT64 RamFree;
  357. SYS_INT64 VirtTotal;
  358. if (SysMemoryInfo(&RamTotal, &RamFree, &VirtTotal, &FreeSpace) < 0)
  359. return (ErrGetErrorCode());
  360. }
  361. if (FreeSpace < (SYS_INT64) ulMinSpace) {
  362. ErrSetErrorCode(ERR_LOW_VM_SPACE);
  363. return (ERR_LOW_VM_SPACE);
  364. }
  365. return (0);
  366. }