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

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 "AppDefines.h"
  25. #define SYS_INT_CALL()              (!iShutDown && (errno == EINTR))
  26. #define SHUTDOWN_RECV_TIMEOUT       2
  27. #define SAIN_Addr(s)                (s).sin_addr.s_addr
  28. #define SCHED_PRIORITY_INC          5
  29. #define MIN_TCP_SEND_SIZE           (1024 * 8)
  30. #define MAX_TCP_SEND_SIZE           (1024 * 128)
  31. #define K_IO_TIME_RATIO             8
  32. #define WAIT_PID_TIME_STEP          250
  33. #define WAIT_TIMEO_EXIT_STATUS      255
  34. #define WAIT_ERROR_EXIT_STATUS      254
  35. #define MAX_STACK_SHIFT             2048
  36. #define STACK_ALIGN_BYTES           sizeof(int)
  37. struct SemData {
  38. pthread_mutex_t Mtx;
  39. pthread_cond_t WaitCond;
  40. int iSemCounter;
  41. int iMaxCount;
  42. };
  43. struct MutexData {
  44. pthread_mutex_t Mtx;
  45. pthread_cond_t WaitCond;
  46. int iLocked;
  47. };
  48. struct EventData {
  49. pthread_mutex_t Mtx;
  50. pthread_cond_t WaitCond;
  51. int iSignaled;
  52. int iManualReset;
  53. };
  54. struct WaitData {
  55. pthread_mutex_t Mtx;
  56. pthread_cond_t WaitCond;
  57. };
  58. struct ThrData {
  59. pthread_t ThreadId;
  60. unsigned int (*ThreadProc) (void *);
  61. void *pThreadData;
  62. pthread_mutex_t Mtx;
  63. pthread_cond_t ExitWaitCond;
  64. int iThreadEnded;
  65. int iExitCode;
  66. int iUseCount;
  67. };
  68. union FilledDirent {
  69. struct dirent DE;
  70. char Pad[sizeof(struct dirent) + NAME_MAX];
  71. };
  72. struct FileFindData {
  73. char szPath[SYS_MAX_PATH];
  74. DIR *pDIR;
  75. FilledDirent FDE;
  76. struct stat FS;
  77. };
  78. static int SysSetSignal(int iSigNo, void (*pSigProc) (int));
  79. static char const *SysGetLastError(void);
  80. static void SysIgnoreProc(int iSignal);
  81. static int SysSetSockNoDelay(SYS_SOCKET SockFD, int iNoDelay);
  82. static int SysSetSocketsOptions(SYS_SOCKET SockFD);
  83. static int SysFreeThreadData(ThrData * pTD);
  84. static void *SysThreadStartup(void *pThreadData);
  85. static int SysThreadSetup(ThrData * pTD);
  86. static void SysThreadCleanup(ThrData * pTD);
  87. #if defined(__OPENBSD__) || defined(__NETBSD__)
  88. static int SysGetPriorityMin(int iPolicy);
  89. static int SysGetPriorityMax(int iPolicy);
  90. #endif // #if defined(__OPENBSD__) || defined(__NETBSD__)
  91. static int SysSafeMsSleep(int iMsTimeout);
  92. static int SysWaitPID(pid_t PID, int *piExitCode, int iTimeout);
  93. static void SysBreakHandlerRoutine(int iSignal);
  94. static int SysSetupWait(WaitData * pWD);
  95. static int SysWait(WaitData * pWD, int iMsTimeout);
  96. static void SysCleanupWait(WaitData * pWD);
  97. static unsigned int SysStkCall(unsigned int (*pProc) (void *), void *pData);
  98. static volatile int iShutDown = 0;
  99. static unsigned int uSRandBase;
  100. static pthread_mutex_t LogMutex = PTHREAD_MUTEX_INITIALIZER;
  101. static void (*SysBreakHandler) (void) = NULL;
  102. static int iSndBufSize = -1, iRcvBufSize = -1;
  103. static int SysSetSignal(int iSigNo, void (*pSigProc) (int))
  104. {
  105. signal(iSigNo, pSigProc);
  106. return (0);
  107. }
  108. static char const *SysGetLastError(void)
  109. {
  110. static char szMessage[1024] = "";
  111. snprintf(szMessage, sizeof(szMessage) - 1, "(0x%lX) %s", (unsigned long) errno,
  112.  strerror(errno));
  113. return (szMessage);
  114. }
  115. static void SysIgnoreProc(int iSignal)
  116. {
  117. SysSetSignal(iSignal, SysIgnoreProc);
  118. }
  119. int SysInitLibrary(void)
  120. {
  121. iShutDown = 0;
  122. tzset();
  123. uSRandBase = (unsigned int) time(NULL);
  124. if (SysThreadSetup(NULL) < 0)
  125. return (ErrGetErrorCode());
  126. return (0);
  127. }
  128. void SysCleanupLibrary(void)
  129. {
  130. SysThreadCleanup(NULL);
  131. }
  132. int SysShutdownLibrary(int iMode)
  133. {
  134. iShutDown++;
  135. kill(0, SIGQUIT);
  136. return (0);
  137. }
  138. int SysSetupSocketBuffers(int *piSndBufSize, int *piRcvBufSize)
  139. {
  140. if (piSndBufSize != NULL)
  141. iSndBufSize = *piSndBufSize;
  142. if (piRcvBufSize != NULL)
  143. iRcvBufSize = *piRcvBufSize;
  144. return (0);
  145. }
  146. SYS_SOCKET SysCreateSocket(int iAddressFamily, int iType, int iProtocol)
  147. {
  148. int SockFD = socket(AF_INET, iType, iProtocol);
  149. if (SockFD == -1) {
  150. ErrSetErrorCode(ERR_SOCKET_CREATE);
  151. return (SYS_INVALID_SOCKET);
  152. }
  153. if (SysSetSocketsOptions((SYS_SOCKET) SockFD) < 0) {
  154. SysCloseSocket((SYS_SOCKET) SockFD);
  155. return (SYS_INVALID_SOCKET);
  156. }
  157. return ((SYS_SOCKET) SockFD);
  158. }
  159. static int SysSetSockNoDelay(SYS_SOCKET SockFD, int iNoDelay)
  160. {
  161. long lSockFlags = fcntl((int) SockFD, F_GETFL, 0);
  162. if (lSockFlags == -1) {
  163. ErrSetErrorCode(ERR_NETWORK);
  164. return (ERR_NETWORK);
  165. }
  166. if (iNoDelay)
  167. lSockFlags |= O_NONBLOCK;
  168. else
  169. lSockFlags &= ~O_NONBLOCK;
  170. if (fcntl((int) SockFD, F_SETFL, lSockFlags) == -1) {
  171. ErrSetErrorCode(ERR_NETWORK);
  172. return (ERR_NETWORK);
  173. }
  174. return (0);
  175. }
  176. static int SysSetSocketsOptions(SYS_SOCKET SockFD)
  177. {
  178. ///////////////////////////////////////////////////////////////////////////////
  179. //  Set socket buffer sizes
  180. ///////////////////////////////////////////////////////////////////////////////
  181. if (iSndBufSize > 0) {
  182. int iSize = iSndBufSize;
  183. setsockopt((int) SockFD, SOL_SOCKET, SO_SNDBUF, (const char *) &iSize,
  184.    sizeof(iSize));
  185. }
  186. if (iRcvBufSize > 0) {
  187. int iSize = iRcvBufSize;
  188. setsockopt((int) SockFD, SOL_SOCKET, SO_RCVBUF, (const char *) &iSize,
  189.    sizeof(iSize));
  190. }
  191. int iActivate = 1;
  192. if (setsockopt(SockFD, SOL_SOCKET, SO_REUSEADDR, (const char *) &iActivate,
  193.        sizeof(iActivate)) != 0) {
  194. ErrSetErrorCode(ERR_SETSOCKOPT);
  195. return (ERR_SETSOCKOPT);
  196. }
  197. ///////////////////////////////////////////////////////////////////////////////
  198. //  Disable linger
  199. ///////////////////////////////////////////////////////////////////////////////
  200. struct linger Ling;
  201. ZeroData(Ling);
  202. Ling.l_onoff = 0;
  203. Ling.l_linger = 0;
  204. setsockopt(SockFD, SOL_SOCKET, SO_LINGER, (const char *) &Ling, sizeof(Ling));
  205. ///////////////////////////////////////////////////////////////////////////////
  206. //  Set KEEPALIVE if supported
  207. ///////////////////////////////////////////////////////////////////////////////
  208. setsockopt(SockFD, SOL_SOCKET, SO_KEEPALIVE, (const char *) &iActivate,
  209.    sizeof(iActivate));
  210. return (0);
  211. }
  212. void SysCloseSocket(SYS_SOCKET SockFD)
  213. {
  214. close(SockFD);
  215. }
  216. int SysBindSocket(SYS_SOCKET SockFD, const struct sockaddr *SockName, int iNameLen)
  217. {
  218. if (bind((int) SockFD, SockName, iNameLen) == -1) {
  219. ErrSetErrorCode(ERR_SOCKET_BIND);
  220. return (ERR_SOCKET_BIND);
  221. }
  222. return (0);
  223. }
  224. void SysListenSocket(SYS_SOCKET SockFD, int iConnections)
  225. {
  226. listen((int) SockFD, iConnections);
  227. }
  228. int SysRecvData(SYS_SOCKET SockFD, char *pszBuffer, int iBufferSize, int iTimeout)
  229. {
  230. struct pollfd pfds;
  231. ZeroData(pfds);
  232. pfds.fd = (int) SockFD;
  233. pfds.events = POLLIN;
  234. int iPollResult = poll(&pfds, 1, iTimeout * 1000);
  235. if (iPollResult == -1) {
  236. ErrSetErrorCode(ERR_NETWORK);
  237. return (ERR_NETWORK);
  238. }
  239. if (iPollResult == 0) {
  240. ErrSetErrorCode(ERR_TIMEOUT);
  241. return (ERR_TIMEOUT);
  242. }
  243. int iRecvBytes;
  244. while (((iRecvBytes = recv((int) SockFD, pszBuffer, iBufferSize, 0)) == -1) &&
  245.        SYS_INT_CALL());
  246. if (iRecvBytes == -1) {
  247. ErrSetErrorCode(ERR_NETWORK);
  248. return (ERR_NETWORK);
  249. }
  250. return (iRecvBytes);
  251. }
  252. int SysRecv(SYS_SOCKET SockFD, char *pszBuffer, int iBufferSize, int iTimeout)
  253. {
  254. int iRtxBytes = 0;
  255. while (iRtxBytes < iBufferSize) {
  256. int iRtxCurrent = SysRecvData(SockFD, pszBuffer + iRtxBytes,
  257.       iBufferSize - iRtxBytes, iTimeout);
  258. if (iRtxCurrent <= 0)
  259. return (iRtxBytes);
  260. iRtxBytes += iRtxCurrent;
  261. }
  262. return (iRtxBytes);
  263. }
  264. int SysRecvDataFrom(SYS_SOCKET SockFD, struct sockaddr *pFrom, int iFromlen,
  265.     char *pszBuffer, int iBufferSize, int iTimeout)
  266. {
  267. struct pollfd pfds;
  268. ZeroData(pfds);
  269. pfds.fd = (int) SockFD;
  270. pfds.events = POLLIN;
  271. int iPollResult = poll(&pfds, 1, iTimeout * 1000);
  272. if (iPollResult == -1) {
  273. ErrSetErrorCode(ERR_NETWORK);
  274. return (ERR_NETWORK);
  275. }
  276. if (iPollResult == 0) {
  277. ErrSetErrorCode(ERR_TIMEOUT);
  278. return (ERR_TIMEOUT);
  279. }
  280. socklen_t SockALen = (socklen_t) iFromlen;
  281. int iRecvBytes;
  282. while (((iRecvBytes = recvfrom((int) SockFD, pszBuffer, iBufferSize, 0,
  283.        pFrom, &SockALen)) == -1) && SYS_INT_CALL());
  284. if (iRecvBytes == -1) {
  285. ErrSetErrorCode(ERR_NETWORK);
  286. return (ERR_NETWORK);
  287. }
  288. return (iRecvBytes);
  289. }
  290. int SysSendData(SYS_SOCKET SockFD, char const *pszBuffer, int iBufferSize, int iTimeout)
  291. {
  292. struct pollfd pfds;
  293. ZeroData(pfds);
  294. pfds.fd = (int) SockFD;
  295. pfds.events = POLLOUT;
  296. int iPollResult = poll(&pfds, 1, iTimeout * 1000);
  297. if (iPollResult == -1) {
  298. ErrSetErrorCode(ERR_NETWORK);
  299. return (ERR_NETWORK);
  300. }
  301. if (iPollResult == 0) {
  302. ErrSetErrorCode(ERR_TIMEOUT);
  303. return (ERR_TIMEOUT);
  304. }
  305. int iSendBytes;
  306. while (((iSendBytes = send((int) SockFD, pszBuffer, iBufferSize, 0)) == -1) &&
  307.        SYS_INT_CALL());
  308. if (iSendBytes == -1) {
  309. ErrSetErrorCode(ERR_NETWORK);
  310. return (ERR_NETWORK);
  311. }
  312. return (iSendBytes);
  313. }
  314. int SysSend(SYS_SOCKET SockFD, char const *pszBuffer, int iBufferSize, int iTimeout)
  315. {
  316. int iRtxBytes = 0;
  317. while (iRtxBytes < iBufferSize) {
  318. int iRtxCurrent = SysSendData(SockFD, pszBuffer + iRtxBytes,
  319.       iBufferSize - iRtxBytes, iTimeout);
  320. if (iRtxCurrent <= 0)
  321. return (iRtxBytes);
  322. iRtxBytes += iRtxCurrent;
  323. }
  324. return (iRtxBytes);
  325. }
  326. int SysSendDataTo(SYS_SOCKET SockFD, const struct sockaddr *pTo,
  327.   int iToLen, char const *pszBuffer, int iBufferSize, int iTimeout)
  328. {
  329. struct pollfd pfds;
  330. ZeroData(pfds);
  331. pfds.fd = (int) SockFD;
  332. pfds.events = POLLOUT;
  333. int iPollResult = poll(&pfds, 1, iTimeout * 1000);
  334. if (iPollResult == -1) {
  335. ErrSetErrorCode(ERR_NETWORK);
  336. return (ERR_NETWORK);
  337. }
  338. if (iPollResult == 0) {
  339. ErrSetErrorCode(ERR_TIMEOUT);
  340. return (ERR_TIMEOUT);
  341. }
  342. int iSendBytes;
  343. while (((iSendBytes = sendto((int) SockFD, pszBuffer, iBufferSize, 0, pTo, iToLen)) == -1)
  344.        && SYS_INT_CALL());
  345. if (iSendBytes == -1) {
  346. ErrSetErrorCode(ERR_NETWORK);
  347. return (ERR_NETWORK);
  348. }
  349. return (iSendBytes);
  350. }
  351. int SysConnect(SYS_SOCKET SockFD, const SYS_INET_ADDR * pSockName, int iNameLen, int iTimeout)
  352. {
  353. if (SysSetSockNoDelay(SockFD, 1) < 0)
  354. return (ErrGetErrorCode());
  355. if (connect((int) SockFD, (const struct sockaddr *) &pSockName->Addr, iNameLen) == 0) {
  356. SysSetSockNoDelay(SockFD, 0);
  357. return (0);
  358. }
  359. if ((errno != EINPROGRESS) && (errno != EWOULDBLOCK)) {
  360. SysSetSockNoDelay(SockFD, 0);
  361. ErrSetErrorCode(ERR_NETWORK);
  362. return (ERR_NETWORK);
  363. }
  364. struct pollfd pfds;
  365. ZeroData(pfds);
  366. pfds.fd = (int) SockFD;
  367. pfds.events = POLLOUT;
  368. int iPollResult = poll(&pfds, 1, iTimeout * 1000);
  369. SysSetSockNoDelay(SockFD, 0);
  370. if (iPollResult == -1) {
  371. ErrSetErrorCode(ERR_NETWORK);
  372. return (ERR_NETWORK);
  373. }
  374. if (iPollResult == 0) {
  375. ErrSetErrorCode(ERR_TIMEOUT);
  376. return (ERR_TIMEOUT);
  377. }
  378. return (0);
  379. }
  380. SYS_SOCKET SysAccept(SYS_SOCKET SockFD, SYS_INET_ADDR * pSockName, int *iNameLen, int iTimeout)
  381. {
  382. struct pollfd pfds;
  383. ZeroData(pfds);
  384. pfds.fd = (int) SockFD;
  385. pfds.events = POLLIN;
  386. int iPollResult = poll(&pfds, 1, iTimeout * 1000);
  387. if (iPollResult == -1) {
  388. ErrSetErrorCode(ERR_NETWORK);
  389. return (SYS_INVALID_SOCKET);
  390. }
  391. if (iPollResult == 0) {
  392. ErrSetErrorCode(ERR_TIMEOUT);
  393. return (SYS_INVALID_SOCKET);
  394. }
  395. socklen_t SockALen = (socklen_t) * iNameLen;
  396. int iAcptSock = accept((int) SockFD,
  397.        (struct sockaddr *) &pSockName->Addr, &SockALen);
  398. if (iAcptSock == -1) {
  399. ErrSetErrorCode(ERR_NETWORK);
  400. return (SYS_INVALID_SOCKET);
  401. }
  402. if (SysSetSocketsOptions((SYS_SOCKET) iAcptSock) < 0) {
  403. SysCloseSocket((SYS_SOCKET) iAcptSock);
  404. return (SYS_INVALID_SOCKET);
  405. }
  406. *iNameLen = (int) SockALen;
  407. return ((SYS_SOCKET) iAcptSock);
  408. }
  409. int SysSelect(int iMaxFD, SYS_fd_set * pReadFDs, SYS_fd_set * pWriteFDs, SYS_fd_set * pExcptFDs,
  410.       int iTimeout)
  411. {
  412. struct timeval TV;
  413. ZeroData(TV);
  414. TV.tv_sec = iTimeout;
  415. TV.tv_usec = 0;
  416. int iSelectResult = select(iMaxFD + 1, pReadFDs, pWriteFDs, pExcptFDs, &TV);
  417. if (iSelectResult == -1) {
  418. ErrSetErrorCode(ERR_SELECT);
  419. return (ERR_SELECT);
  420. }
  421. if (iSelectResult == 0) {
  422. ErrSetErrorCode(ERR_TIMEOUT);
  423. return (ERR_TIMEOUT);
  424. }
  425. return (iSelectResult);
  426. }
  427. int SysSendFile(SYS_SOCKET SockFD, char const *pszFileName, unsigned long ulBaseOffset,
  428. unsigned long ulEndOffset, int iTimeout)
  429. {
  430. int iFileID = open(pszFileName, O_RDONLY);
  431. if (iFileID == -1) {
  432. ErrSetErrorCode(ERR_FILE_OPEN, pszFileName);
  433. return (ERR_FILE_OPEN);
  434. }
  435. unsigned long ulFileSize = (unsigned long) lseek(iFileID, 0, SEEK_END);
  436. lseek(iFileID, 0, SEEK_SET);
  437. void *pMapAddress = (void *) mmap((char *) 0, (size_t) ulFileSize, PROT_READ,
  438.   MAP_SHARED, iFileID, 0);
  439. if (pMapAddress == (void *) -1) {
  440. close(iFileID);
  441. ErrSetErrorCode(ERR_MMAP);
  442. return (ERR_MMAP);
  443. }
  444. ///////////////////////////////////////////////////////////////////////////////
  445. //  Send the file
  446. ///////////////////////////////////////////////////////////////////////////////
  447. int iSndBuffSize = MIN_TCP_SEND_SIZE;
  448. unsigned long ulCurrOffset = ulBaseOffset;
  449. unsigned long ulSndEndOffset =
  450. (ulEndOffset != (unsigned long) -1) ? ulEndOffset : ulFileSize;
  451. char *pszBuffer = (char *) pMapAddress + ulBaseOffset;
  452. time_t tStart;
  453. while (ulCurrOffset < ulSndEndOffset) {
  454. int iCurrSend = (int) Min(iSndBuffSize, ulSndEndOffset - ulCurrOffset);
  455. tStart = time(NULL);
  456. if ((iCurrSend = SysSendData(SockFD, pszBuffer, iCurrSend, iTimeout)) < 0) {
  457. ErrorPush();
  458. munmap((char *) pMapAddress, (size_t) ulFileSize);
  459. close(iFileID);
  460. return (ErrorPop());
  461. }
  462. if ((((time(NULL) - tStart) * K_IO_TIME_RATIO) < iTimeout) &&
  463.     (iSndBuffSize < MAX_TCP_SEND_SIZE))
  464. iSndBuffSize = Min(iSndBuffSize * 2, MAX_TCP_SEND_SIZE);
  465. pszBuffer += iCurrSend;
  466. ulCurrOffset += (unsigned long) iCurrSend;
  467. }
  468. munmap((char *) pMapAddress, (size_t) ulFileSize);
  469. close(iFileID);
  470. return (0);
  471. }
  472. int SysSetupAddress(SYS_INET_ADDR & AddrInfo, int iFamily,
  473.     NET_ADDRESS const &NetAddr, int iPortNo)
  474. {
  475. ZeroData(AddrInfo);
  476. AddrInfo.Addr.sin_family = iFamily;
  477. SAIN_Addr(AddrInfo.Addr) = NetAddr;
  478. AddrInfo.Addr.sin_port = htons((short) iPortNo);
  479. return (0);
  480. }
  481. int SysGetAddrAddress(SYS_INET_ADDR const &AddrInfo, NET_ADDRESS & NetAddr)
  482. {
  483. NetAddr = SAIN_Addr(AddrInfo.Addr);
  484. return (0);
  485. }
  486. int SysGetAddrPort(SYS_INET_ADDR const &AddrInfo)
  487. {
  488. return (ntohs(AddrInfo.Addr.sin_port));
  489. }
  490. int SysSetAddrAddress(SYS_INET_ADDR & AddrInfo, NET_ADDRESS const &NetAddr)
  491. {
  492. SAIN_Addr(AddrInfo.Addr) = NetAddr;
  493. return (0);
  494. }
  495. int SysSetAddrPort(SYS_INET_ADDR & AddrInfo, int iPortNo)
  496. {
  497. AddrInfo.Addr.sin_port = htons((short) iPortNo);
  498. return (0);
  499. }
  500. int SysGetHostByName(char const *pszName, NET_ADDRESS & NetAddr)
  501. {
  502. struct hostent *pHostEnt = gethostbyname(pszName);
  503. if ((pHostEnt == NULL) || (pHostEnt->h_addr_list[0] == NULL)) {
  504. ErrSetErrorCode(ERR_BAD_SERVER_ADDR, pszName);
  505. return (ERR_BAD_SERVER_ADDR);
  506. }
  507. memcpy(&NetAddr, pHostEnt->h_addr_list[0], sizeof(NetAddr));
  508. return (0);
  509. }
  510. int SysGetHostByAddr(SYS_INET_ADDR const &AddrInfo, char *pszFQDN)
  511. {
  512. struct hostent *pHostEnt = gethostbyaddr((char *) &SAIN_Addr(AddrInfo.Addr),
  513.  sizeof(SAIN_Addr(AddrInfo.Addr)), AF_INET);
  514. if ((pHostEnt == NULL) || (pHostEnt->h_name == NULL)) {
  515. char szIP[128] = "???.???.???.???";
  516. ErrSetErrorCode(ERR_GET_SOCK_HOST, SysInetNToA(AddrInfo, szIP));
  517. return (ERR_GET_SOCK_HOST);
  518. }
  519. strcpy(pszFQDN, pHostEnt->h_name);
  520. return (0);
  521. }
  522. int SysGetPeerInfo(SYS_SOCKET SockFD, SYS_INET_ADDR & AddrInfo)
  523. {
  524. ZeroData(AddrInfo);
  525. socklen_t InfoSize = sizeof(AddrInfo.Addr);
  526. if (getpeername(SockFD, (struct sockaddr *) &AddrInfo.Addr, &InfoSize) == -1) {
  527. ErrSetErrorCode(ERR_GET_PEER_INFO);
  528. return (ERR_GET_PEER_INFO);
  529. }
  530. return (0);
  531. }
  532. int SysGetSockInfo(SYS_SOCKET SockFD, SYS_INET_ADDR & AddrInfo)
  533. {
  534. ZeroData(AddrInfo);
  535. socklen_t InfoSize = sizeof(AddrInfo.Addr);
  536. if (getsockname(SockFD, (struct sockaddr *) &AddrInfo.Addr, &InfoSize) == -1) {
  537. ErrSetErrorCode(ERR_GET_SOCK_INFO);
  538. return (ERR_GET_SOCK_INFO);
  539. }
  540. return (0);
  541. }
  542. char *SysInetNToA(SYS_INET_ADDR const &AddrInfo, char *pszIP)
  543. {
  544. union {
  545. unsigned int a;
  546. unsigned char b[4];
  547. } UAddr;
  548. memcpy(&UAddr, &AddrInfo.Addr.sin_addr, sizeof(UAddr));
  549. sprintf(pszIP, "%u.%u.%u.%u",
  550. (unsigned int) UAddr.b[0],
  551. (unsigned int) UAddr.b[1], (unsigned int) UAddr.b[2], (unsigned int) UAddr.b[3]);
  552. return (pszIP);
  553. }
  554. int SysInetAddr(char const *pszDotName, NET_ADDRESS & NetAddr)
  555. {
  556. if ((NetAddr = (NET_ADDRESS) inet_addr(pszDotName)) == SYS_INVALID_NET_ADDRESS) {
  557. ErrSetErrorCode(ERR_BAD_SERVER_ADDR, pszDotName);
  558. return (ERR_BAD_SERVER_ADDR);
  559. }
  560. return (0);
  561. }
  562. int SysSameAddress(NET_ADDRESS const &NetAddr1, NET_ADDRESS const &NetAddr2)
  563. {
  564. return (memcmp(&NetAddr1, &NetAddr2, sizeof(NET_ADDRESS)) == 0);
  565. }
  566. SYS_SEMAPHORE SysCreateSemaphore(int iInitCount, int iMaxCount)
  567. {
  568. SemData *pSD = (SemData *) SysAlloc(sizeof(SemData));
  569. if (pSD == NULL)
  570. return (SYS_INVALID_SEMAPHORE);
  571. if (pthread_mutex_init(&pSD->Mtx, NULL) != 0) {
  572. SysFree(pSD);
  573. ErrSetErrorCode(ERR_MUTEXINIT, NULL);
  574. return (SYS_INVALID_SEMAPHORE);
  575. }
  576. if (pthread_cond_init(&pSD->WaitCond, NULL) != 0) {
  577. pthread_mutex_destroy(&pSD->Mtx);
  578. SysFree(pSD);
  579. ErrSetErrorCode(ERR_CONDINIT, NULL);
  580. return (SYS_INVALID_SEMAPHORE);
  581. }
  582. pSD->iSemCounter = iInitCount;
  583. pSD->iMaxCount = iMaxCount;
  584. return ((SYS_SEMAPHORE) pSD);
  585. }
  586. int SysCloseSemaphore(SYS_SEMAPHORE hSemaphore)
  587. {
  588. SemData *pSD = (SemData *) hSemaphore;
  589. pthread_cond_destroy(&pSD->WaitCond);
  590. pthread_mutex_destroy(&pSD->Mtx);
  591. SysFree(pSD);
  592. return (0);
  593. }
  594. int SysWaitSemaphore(SYS_SEMAPHORE hSemaphore, int iTimeout)
  595. {
  596. SemData *pSD = (SemData *) hSemaphore;
  597. pthread_mutex_lock(&pSD->Mtx);
  598. if (iTimeout == SYS_INFINITE_TIMEOUT) {
  599. while (pSD->iSemCounter <= 0) {
  600. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pSD->Mtx);
  601. pthread_cond_wait(&pSD->WaitCond, &pSD->Mtx);
  602. pthread_cleanup_pop(0);
  603. }
  604. pSD->iSemCounter -= 1;
  605. } else {
  606. struct timeval tvNow;
  607. struct timespec tsTimeout;
  608. gettimeofday(&tvNow, NULL);
  609. tsTimeout.tv_sec = tvNow.tv_sec + iTimeout;
  610. tsTimeout.tv_nsec = tvNow.tv_usec * 1000;
  611. int iRetCode = 0;
  612. while ((pSD->iSemCounter <= 0) && (iRetCode != ETIMEDOUT)) {
  613. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pSD->Mtx);
  614. iRetCode = pthread_cond_timedwait(&pSD->WaitCond, &pSD->Mtx, &tsTimeout);
  615. pthread_cleanup_pop(0);
  616. }
  617. if (iRetCode == ETIMEDOUT) {
  618. pthread_mutex_unlock(&pSD->Mtx);
  619. ErrSetErrorCode(ERR_TIMEOUT);
  620. return (ERR_TIMEOUT);
  621. }
  622. pSD->iSemCounter -= 1;
  623. }
  624. pthread_mutex_unlock(&pSD->Mtx);
  625. return (0);
  626. }
  627. int SysReleaseSemaphore(SYS_SEMAPHORE hSemaphore, int iCount)
  628. {
  629. SemData *pSD = (SemData *) hSemaphore;
  630. pthread_mutex_lock(&pSD->Mtx);
  631. pSD->iSemCounter += iCount;
  632. if (pSD->iSemCounter > 0) {
  633. if (pSD->iSemCounter > 1)
  634. pthread_cond_broadcast(&pSD->WaitCond);
  635. else
  636. pthread_cond_signal(&pSD->WaitCond);
  637. }
  638. pthread_mutex_unlock(&pSD->Mtx);
  639. return (0);
  640. }
  641. int SysTryWaitSemaphore(SYS_SEMAPHORE hSemaphore)
  642. {
  643. SemData *pSD = (SemData *) hSemaphore;
  644. pthread_mutex_lock(&pSD->Mtx);
  645. if (pSD->iSemCounter <= 0) {
  646. pthread_mutex_unlock(&pSD->Mtx);
  647. ErrSetErrorCode(ERR_TIMEOUT);
  648. return (ERR_TIMEOUT);
  649. }
  650. pSD->iSemCounter -= 1;
  651. pthread_mutex_unlock(&pSD->Mtx);
  652. return (0);
  653. }
  654. SYS_MUTEX SysCreateMutex(void)
  655. {
  656. MutexData *pMD = (MutexData *) SysAlloc(sizeof(MutexData));
  657. if (pMD == NULL)
  658. return (SYS_INVALID_MUTEX);
  659. if (pthread_mutex_init(&pMD->Mtx, NULL) != 0) {
  660. SysFree(pMD);
  661. ErrSetErrorCode(ERR_MUTEXINIT);
  662. return (SYS_INVALID_MUTEX);
  663. }
  664. if (pthread_cond_init(&pMD->WaitCond, NULL) != 0) {
  665. pthread_mutex_destroy(&pMD->Mtx);
  666. SysFree(pMD);
  667. ErrSetErrorCode(ERR_CONDINIT);
  668. return (SYS_INVALID_MUTEX);
  669. }
  670. pMD->iLocked = 0;
  671. return ((SYS_MUTEX) pMD);
  672. }
  673. int SysCloseMutex(SYS_MUTEX hMutex)
  674. {
  675. MutexData *pMD = (MutexData *) hMutex;
  676. pthread_cond_destroy(&pMD->WaitCond);
  677. pthread_mutex_destroy(&pMD->Mtx);
  678. SysFree(pMD);
  679. return (0);
  680. }
  681. int SysLockMutex(SYS_MUTEX hMutex, int iTimeout)
  682. {
  683. MutexData *pMD = (MutexData *) hMutex;
  684. pthread_mutex_lock(&pMD->Mtx);
  685. if (iTimeout == SYS_INFINITE_TIMEOUT) {
  686. while (pMD->iLocked) {
  687. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pMD->Mtx);
  688. pthread_cond_wait(&pMD->WaitCond, &pMD->Mtx);
  689. pthread_cleanup_pop(0);
  690. }
  691. pMD->iLocked = 1;
  692. } else {
  693. struct timeval tvNow;
  694. struct timespec tsTimeout;
  695. gettimeofday(&tvNow, NULL);
  696. tsTimeout.tv_sec = tvNow.tv_sec + iTimeout;
  697. tsTimeout.tv_nsec = tvNow.tv_usec * 1000;
  698. int iRetCode = 0;
  699. while (pMD->iLocked && (iRetCode != ETIMEDOUT)) {
  700. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pMD->Mtx);
  701. iRetCode = pthread_cond_timedwait(&pMD->WaitCond, &pMD->Mtx, &tsTimeout);
  702. pthread_cleanup_pop(0);
  703. }
  704. if (iRetCode == ETIMEDOUT) {
  705. pthread_mutex_unlock(&pMD->Mtx);
  706. ErrSetErrorCode(ERR_TIMEOUT);
  707. return (ERR_TIMEOUT);
  708. }
  709. pMD->iLocked = 1;
  710. }
  711. pthread_mutex_unlock(&pMD->Mtx);
  712. return (0);
  713. }
  714. int SysUnlockMutex(SYS_MUTEX hMutex)
  715. {
  716. MutexData *pMD = (MutexData *) hMutex;
  717. pthread_mutex_lock(&pMD->Mtx);
  718. pMD->iLocked = 0;
  719. pthread_cond_signal(&pMD->WaitCond);
  720. pthread_mutex_unlock(&pMD->Mtx);
  721. return (0);
  722. }
  723. int SysTryLockMutex(SYS_MUTEX hMutex)
  724. {
  725. MutexData *pMD = (MutexData *) hMutex;
  726. pthread_mutex_lock(&pMD->Mtx);
  727. if (pMD->iLocked) {
  728. pthread_mutex_unlock(&pMD->Mtx);
  729. ErrSetErrorCode(ERR_TIMEOUT);
  730. return (ERR_TIMEOUT);
  731. }
  732. pMD->iLocked = 1;
  733. pthread_mutex_unlock(&pMD->Mtx);
  734. return (0);
  735. }
  736. SYS_EVENT SysCreateEvent(int iManualReset)
  737. {
  738. EventData *pED = (EventData *) SysAlloc(sizeof(EventData));
  739. if (pED == NULL)
  740. return (SYS_INVALID_EVENT);
  741. if (pthread_mutex_init(&pED->Mtx, NULL) != 0) {
  742. SysFree(pED);
  743. ErrSetErrorCode(ERR_MUTEXINIT);
  744. return (SYS_INVALID_EVENT);
  745. }
  746. if (pthread_cond_init(&pED->WaitCond, NULL) != 0) {
  747. pthread_mutex_destroy(&pED->Mtx);
  748. SysFree(pED);
  749. ErrSetErrorCode(ERR_CONDINIT);
  750. return (SYS_INVALID_EVENT);
  751. }
  752. pED->iSignaled = 0;
  753. pED->iManualReset = iManualReset;
  754. return ((SYS_EVENT) pED);
  755. }
  756. int SysCloseEvent(SYS_EVENT hEvent)
  757. {
  758. EventData *pED = (EventData *) hEvent;
  759. pthread_cond_destroy(&pED->WaitCond);
  760. pthread_mutex_destroy(&pED->Mtx);
  761. SysFree(pED);
  762. return (0);
  763. }
  764. int SysWaitEvent(SYS_EVENT hEvent, int iTimeout)
  765. {
  766. EventData *pED = (EventData *) hEvent;
  767. pthread_mutex_lock(&pED->Mtx);
  768. if (iTimeout == SYS_INFINITE_TIMEOUT) {
  769. while (!pED->iSignaled) {
  770. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pED->Mtx);
  771. pthread_cond_wait(&pED->WaitCond, &pED->Mtx);
  772. pthread_cleanup_pop(0);
  773. }
  774. if (!pED->iManualReset)
  775. pED->iSignaled = 0;
  776. } else {
  777. struct timeval tvNow;
  778. struct timespec tsTimeout;
  779. gettimeofday(&tvNow, NULL);
  780. tsTimeout.tv_sec = tvNow.tv_sec + iTimeout;
  781. tsTimeout.tv_nsec = tvNow.tv_usec * 1000;
  782. int iRetCode = 0;
  783. while (!pED->iSignaled && (iRetCode != ETIMEDOUT)) {
  784. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pED->Mtx);
  785. iRetCode = pthread_cond_timedwait(&pED->WaitCond, &pED->Mtx, &tsTimeout);
  786. pthread_cleanup_pop(0);
  787. }
  788. if (iRetCode == ETIMEDOUT) {
  789. pthread_mutex_unlock(&pED->Mtx);
  790. ErrSetErrorCode(ERR_TIMEOUT);
  791. return (ERR_TIMEOUT);
  792. }
  793. if (!pED->iManualReset)
  794. pED->iSignaled = 0;
  795. }
  796. pthread_mutex_unlock(&pED->Mtx);
  797. return (0);
  798. }
  799. int SysSetEvent(SYS_EVENT hEvent)
  800. {
  801. EventData *pED = (EventData *) hEvent;
  802. pthread_mutex_lock(&pED->Mtx);
  803. pED->iSignaled = 1;
  804. if (pED->iManualReset)
  805. pthread_cond_broadcast(&pED->WaitCond);
  806. else
  807. pthread_cond_signal(&pED->WaitCond);
  808. pthread_mutex_unlock(&pED->Mtx);
  809. return (0);
  810. }
  811. int SysResetEvent(SYS_EVENT hEvent)
  812. {
  813. EventData *pED = (EventData *) hEvent;
  814. pthread_mutex_lock(&pED->Mtx);
  815. pED->iSignaled = 0;
  816. pthread_mutex_unlock(&pED->Mtx);
  817. return (0);
  818. }
  819. int SysTryWaitEvent(SYS_EVENT hEvent)
  820. {
  821. EventData *pED = (EventData *) hEvent;
  822. pthread_mutex_lock(&pED->Mtx);
  823. if (!pED->iSignaled) {
  824. pthread_mutex_unlock(&pED->Mtx);
  825. ErrSetErrorCode(ERR_TIMEOUT);
  826. return (ERR_TIMEOUT);
  827. }
  828. if (!pED->iManualReset)
  829. pED->iSignaled = 0;
  830. pthread_mutex_unlock(&pED->Mtx);
  831. return (0);
  832. }
  833. static int SysFreeThreadData(ThrData * pTD)
  834. {
  835. pthread_cond_destroy(&pTD->ExitWaitCond);
  836. pthread_mutex_destroy(&pTD->Mtx);
  837. SysFree(pTD);
  838. return (0);
  839. }
  840. static void *SysThreadStartup(void *pThreadData)
  841. {
  842. ThrData *pTD = (ThrData *) pThreadData;
  843. SysThreadSetup(pTD);
  844. int iExitCode;
  845. pthread_cleanup_push((void (*)(void *)) SysThreadCleanup, pTD);
  846. pTD->iExitCode = iExitCode = SysStkCall(pTD->ThreadProc, pTD->pThreadData);
  847. pthread_cleanup_pop(1);
  848. return ((void *) iExitCode);
  849. }
  850. SYS_THREAD SysCreateThread(unsigned int (*pThreadProc) (void *), void *pThreadData)
  851. {
  852. ThrData *pTD = (ThrData *) SysAlloc(sizeof(ThrData));
  853. if (pTD == NULL)
  854. return (SYS_INVALID_THREAD);
  855. pTD->ThreadProc = pThreadProc;
  856. pTD->pThreadData = pThreadData;
  857. pTD->iThreadEnded = 0;
  858. pTD->iExitCode = -1;
  859. pTD->iUseCount = 2;
  860. if (pthread_mutex_init(&pTD->Mtx, NULL) != 0) {
  861. SysFree(pTD);
  862. ErrSetErrorCode(ERR_MUTEXINIT);
  863. return (SYS_INVALID_THREAD);
  864. }
  865. if (pthread_cond_init(&pTD->ExitWaitCond, NULL) != 0) {
  866. pthread_mutex_destroy(&pTD->Mtx);
  867. SysFree(pTD);
  868. ErrSetErrorCode(ERR_CONDINIT);
  869. return (SYS_INVALID_THREAD);
  870. }
  871. pthread_attr_t ThrAttr;
  872. pthread_attr_init(&ThrAttr);
  873. pthread_attr_setscope(&ThrAttr, PTHREAD_SCOPE_SYSTEM);
  874. if (pthread_create(&pTD->ThreadId, &ThrAttr, SysThreadStartup, pTD) != 0) {
  875. pthread_attr_destroy(&ThrAttr);
  876. pthread_cond_destroy(&pTD->ExitWaitCond);
  877. pthread_mutex_destroy(&pTD->Mtx);
  878. SysFree(pTD);
  879. ErrSetErrorCode(ERR_THREADCREATE);
  880. return (SYS_INVALID_THREAD);
  881. }
  882. pthread_attr_destroy(&ThrAttr);
  883. return ((SYS_THREAD) pTD);
  884. }
  885. SYS_THREAD SysCreateServiceThread(unsigned int (*pThreadProc) (void *), SYS_SOCKET SockFD)
  886. {
  887. return (SysCreateThread(pThreadProc, (void *) SockFD));
  888. }
  889. static int SysThreadSetup(ThrData * pTD)
  890. {
  891. sigset_t SigMask;
  892. sigemptyset(&SigMask);
  893. sigaddset(&SigMask, SIGALRM);
  894. sigaddset(&SigMask, SIGINT);
  895. sigaddset(&SigMask, SIGHUP);
  896. sigaddset(&SigMask, SIGSTOP);
  897. sigaddset(&SigMask, SIGCHLD);
  898. pthread_sigmask(SIG_BLOCK, &SigMask, NULL);
  899. sigemptyset(&SigMask);
  900. sigaddset(&SigMask, SIGQUIT);
  901. pthread_sigmask(SIG_UNBLOCK, &SigMask, NULL);
  902. SysSetSignal(SIGQUIT, SysIgnoreProc);
  903. SysSetSignal(SIGPIPE, SysIgnoreProc);
  904. SysSetSignal(SIGCHLD, SysIgnoreProc);
  905. if (pTD != NULL) {
  906. }
  907. return (0);
  908. }
  909. static void SysThreadCleanup(ThrData * pTD)
  910. {
  911. if (pTD != NULL) {
  912. pthread_mutex_lock(&pTD->Mtx);
  913. pTD->iThreadEnded = 1;
  914. pthread_cond_broadcast(&pTD->ExitWaitCond);
  915. if (--pTD->iUseCount == 0) {
  916. pthread_mutex_unlock(&pTD->Mtx);
  917. SysFreeThreadData(pTD);
  918. } else
  919. pthread_mutex_unlock(&pTD->Mtx);
  920. }
  921. }
  922. void SysCloseThread(SYS_THREAD ThreadID, int iForce)
  923. {
  924. ThrData *pTD = (ThrData *) ThreadID;
  925. pthread_mutex_lock(&pTD->Mtx);
  926. pthread_detach(pTD->ThreadId);
  927. if (iForce && !pTD->iThreadEnded)
  928. pthread_cancel(pTD->ThreadId);
  929. if (--pTD->iUseCount == 0) {
  930. pthread_mutex_unlock(&pTD->Mtx);
  931. SysFreeThreadData(pTD);
  932. } else
  933. pthread_mutex_unlock(&pTD->Mtx);
  934. }
  935. #if defined(__OPENBSD__) || defined(__NETBSD__)
  936. static int SysGetPriorityMin(int iPolicy)
  937. {
  938. int iPriority = 0;
  939. switch (iPolicy) {
  940. case SCHED_FIFO:
  941. iPriority = 0;
  942. break;
  943. case SCHED_OTHER:
  944. iPriority = -20;
  945. break;
  946. case SCHED_RR:
  947. iPriority = 0;
  948. break;
  949. }
  950. return (iPriority);
  951. }
  952. static int SysGetPriorityMax(int iPolicy)
  953. {
  954. int iPriority = 0;
  955. switch (iPolicy) {
  956. case SCHED_FIFO:
  957. iPriority = 31;
  958. break;
  959. case SCHED_OTHER:
  960. iPriority = +20;
  961. break;
  962. case SCHED_RR:
  963. iPriority = 31;
  964. break;
  965. }
  966. return (iPriority);
  967. }
  968. #endif // #if defined(__OPENBSD__) || defined(__NETBSD__)
  969. int SysSetThreadPriority(SYS_THREAD ThreadID, int iPriority)
  970. {
  971. ThrData *pTD = (ThrData *) ThreadID;
  972. int iPolicy;
  973. struct sched_param SchParam;
  974. if (pthread_getschedparam(pTD->ThreadId, &iPolicy, &SchParam) != 0) {
  975. ErrSetErrorCode(ERR_SET_THREAD_PRIORITY);
  976. return (ERR_SET_THREAD_PRIORITY);
  977. }
  978. #if defined(__FREEBSD__) || defined (__DARWIN__)
  979. int iMinPriority = sched_get_priority_min(iPolicy);
  980. int iMaxPriority = sched_get_priority_max(iPolicy);
  981. #else // #if defined(__FREEBSD__)
  982. int iMinPriority = SysGetPriorityMin(iPolicy);
  983. int iMaxPriority = SysGetPriorityMax(iPolicy);
  984. #endif // #if defined(__FREEBSD__)
  985. int iStdPriority = (iMinPriority + iMaxPriority) / 2;
  986. switch (iPriority) {
  987. case (SYS_PRIORITY_NORMAL):
  988. SchParam.sched_priority = iStdPriority;
  989. break;
  990. case (SYS_PRIORITY_LOWER):
  991. SchParam.sched_priority = iStdPriority - (iStdPriority - iMinPriority) / 3;
  992. break;
  993. case (SYS_PRIORITY_HIGHER):
  994. SchParam.sched_priority = iStdPriority + (iStdPriority - iMinPriority) / 3;
  995. break;
  996. }
  997. if (pthread_setschedparam(pTD->ThreadId, iPolicy, &SchParam) != 0) {
  998. ErrSetErrorCode(ERR_SET_THREAD_PRIORITY);
  999. return (ERR_SET_THREAD_PRIORITY);
  1000. }
  1001. return (0);
  1002. }
  1003. int SysWaitThread(SYS_THREAD ThreadID, int iTimeout)
  1004. {
  1005. ThrData *pTD = (ThrData *) ThreadID;
  1006. pthread_mutex_lock(&pTD->Mtx);
  1007. if (iTimeout == SYS_INFINITE_TIMEOUT) {
  1008. while (!pTD->iThreadEnded) {
  1009. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pTD->Mtx);
  1010. pthread_cond_wait(&pTD->ExitWaitCond, &pTD->Mtx);
  1011. pthread_cleanup_pop(0);
  1012. }
  1013. } else {
  1014. struct timeval tvNow;
  1015. struct timespec tsTimeout;
  1016. gettimeofday(&tvNow, NULL);
  1017. tsTimeout.tv_sec = tvNow.tv_sec + iTimeout;
  1018. tsTimeout.tv_nsec = tvNow.tv_usec * 1000;
  1019. int iRetCode = 0;
  1020. while (!pTD->iThreadEnded && (iRetCode != ETIMEDOUT)) {
  1021. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pTD->Mtx);
  1022. iRetCode =
  1023. pthread_cond_timedwait(&pTD->ExitWaitCond, &pTD->Mtx, &tsTimeout);
  1024. pthread_cleanup_pop(0);
  1025. }
  1026. if (iRetCode == ETIMEDOUT) {
  1027. pthread_mutex_unlock(&pTD->Mtx);
  1028. ErrSetErrorCode(ERR_TIMEOUT);
  1029. return (ERR_TIMEOUT);
  1030. }
  1031. }
  1032. pthread_mutex_unlock(&pTD->Mtx);
  1033. return (0);
  1034. }
  1035. unsigned long SysGetCurrentThreadId(void)
  1036. {
  1037. return ((unsigned long) pthread_self());
  1038. }
  1039. static int SysSafeMsSleep(int iMsTimeout)
  1040. {
  1041. struct pollfd Dummy;
  1042. ZeroData(Dummy);
  1043. return ((poll(&Dummy, 0, iMsTimeout) == 0) ? 1 : 0);
  1044. }
  1045. static int SysWaitPID(pid_t PID, int *piExitCode, int iTimeout)
  1046. {
  1047. pid_t ExitPID;
  1048. int iExitStatus;
  1049. int iStatus;
  1050. iTimeout *= 1000;
  1051. do {
  1052. if ((ExitPID = (pid_t) waitpid(PID, &iStatus, WNOHANG)) == PID) {
  1053. if (!WIFEXITED(iStatus))
  1054. return (ERR_WAITPID);
  1055. iExitStatus = WEXITSTATUS(iStatus);
  1056. break;
  1057. }
  1058. SysSafeMsSleep(WAIT_PID_TIME_STEP);
  1059. iTimeout -= WAIT_PID_TIME_STEP;
  1060. } while (iTimeout > 0);
  1061. if (PID != ExitPID)
  1062. return (ERR_TIMEOUT);
  1063. if (piExitCode != NULL)
  1064. *piExitCode = iExitStatus;
  1065. return (0);
  1066. }
  1067. int SysExec(char const *pszCommand, char const *const *pszArgs, int iWaitTimeout,
  1068.     int iPriority, int *piExitStatus)
  1069. {
  1070. int iExitStatus;
  1071. pid_t ChildID;
  1072. pid_t ExitPID;
  1073. pid_t ProcessID;
  1074. int iPPipe[2];
  1075. int iCPipe[2];
  1076. if (pipe(iPPipe) == -1) {
  1077. ErrSetErrorCode(ERR_PIPE);
  1078. return (ERR_PIPE);
  1079. }
  1080. if (pipe(iCPipe) == -1) {
  1081. close(iPPipe[1]);
  1082. close(iPPipe[0]);
  1083. ErrSetErrorCode(ERR_PIPE);
  1084. return (ERR_PIPE);
  1085. }
  1086. ProcessID = fork();
  1087. if (ProcessID == 0) {
  1088. ChildID = fork();
  1089. if (ChildID == 0) {
  1090. close(iPPipe[1]);
  1091. close(iPPipe[0]);
  1092. ///////////////////////////////////////////////////////////////////////////////
  1093. //  Wait for the unlock from the parent
  1094. ///////////////////////////////////////////////////////////////////////////////
  1095. read(iCPipe[0], &ChildID, sizeof(ChildID));
  1096. close(iCPipe[1]);
  1097. close(iCPipe[0]);
  1098. ///////////////////////////////////////////////////////////////////////////////
  1099. //  Execute the command
  1100. ///////////////////////////////////////////////////////////////////////////////
  1101. execv(pszCommand, (char **) pszArgs);
  1102. ///////////////////////////////////////////////////////////////////////////////
  1103. //  We can only use async-signal safe functions, so we use write() directly
  1104. ///////////////////////////////////////////////////////////////////////////////
  1105. write(2, "execv error: cmd='", 18);
  1106. write(2, pszCommand, strlen(pszCommand));
  1107. write(2, "'n", 2);
  1108. _exit(WAIT_ERROR_EXIT_STATUS);
  1109. }
  1110. close(iCPipe[1]);
  1111. close(iCPipe[0]);
  1112. ///////////////////////////////////////////////////////////////////////////////
  1113. //  Tell the parent about the child-child PID
  1114. ///////////////////////////////////////////////////////////////////////////////
  1115. write(iPPipe[1], &ChildID, sizeof(ChildID));
  1116. close(iPPipe[1]);
  1117. close(iPPipe[0]);
  1118. if (ChildID == (pid_t) - 1)
  1119. _exit(WAIT_ERROR_EXIT_STATUS);
  1120. ///////////////////////////////////////////////////////////////////////////////
  1121. //  Wait for the child
  1122. ///////////////////////////////////////////////////////////////////////////////
  1123. iExitStatus = WAIT_TIMEO_EXIT_STATUS;
  1124. if (iWaitTimeout > 0)
  1125. SysWaitPID(ChildID, &iExitStatus, iWaitTimeout);
  1126. _exit(iExitStatus);
  1127. }
  1128. if ((ProcessID == (pid_t) - 1) ||
  1129.     (read(iPPipe[0], &ChildID, sizeof(ChildID)) != sizeof(ChildID))) {
  1130. close(iCPipe[1]);
  1131. close(iCPipe[0]);
  1132. close(iPPipe[1]);
  1133. close(iPPipe[0]);
  1134. ErrSetErrorCode(ERR_FORK);
  1135. return (ERR_FORK);
  1136. }
  1137. close(iPPipe[1]);
  1138. close(iPPipe[0]);
  1139. if (ChildID != (pid_t) - 1) {
  1140. ///////////////////////////////////////////////////////////////////////////////
  1141. //  Set process priority
  1142. ///////////////////////////////////////////////////////////////////////////////
  1143. switch (iPriority) {
  1144. case (SYS_PRIORITY_NORMAL):
  1145. setpriority(PRIO_PROCESS, ChildID, 0);
  1146. break;
  1147. case (SYS_PRIORITY_LOWER):
  1148. setpriority(PRIO_PROCESS, ChildID, SCHED_PRIORITY_INC);
  1149. break;
  1150. case (SYS_PRIORITY_HIGHER):
  1151. setpriority(PRIO_PROCESS, ChildID, -SCHED_PRIORITY_INC);
  1152. break;
  1153. }
  1154. ///////////////////////////////////////////////////////////////////////////////
  1155. //  Unlock the child
  1156. ///////////////////////////////////////////////////////////////////////////////
  1157. write(iCPipe[1], &ChildID, sizeof(ChildID));
  1158. }
  1159. close(iCPipe[1]);
  1160. close(iCPipe[0]);
  1161. ///////////////////////////////////////////////////////////////////////////////
  1162. //  Wait for completion (or timeout)
  1163. ///////////////////////////////////////////////////////////////////////////////
  1164. while (((ExitPID = (pid_t) waitpid(ProcessID, &iExitStatus, 0)) != ProcessID) &&
  1165.        (errno == EINTR));
  1166. if ((ExitPID == ProcessID) && WIFEXITED(iExitStatus))
  1167. iExitStatus = WEXITSTATUS(iExitStatus);
  1168. else
  1169. iExitStatus = WAIT_TIMEO_EXIT_STATUS;
  1170. if (iWaitTimeout > 0) {
  1171. if (iExitStatus == WAIT_TIMEO_EXIT_STATUS) {
  1172. ErrSetErrorCode(ERR_TIMEOUT);
  1173. return (ERR_TIMEOUT);
  1174. }
  1175. if (iExitStatus == WAIT_ERROR_EXIT_STATUS) {
  1176. ErrSetErrorCode(ERR_FORK);
  1177. return (ERR_FORK);
  1178. }
  1179. } else
  1180. iExitStatus = -1;
  1181. if (piExitStatus != NULL)
  1182. *piExitStatus = iExitStatus;
  1183. return (0);
  1184. }
  1185. static void SysBreakHandlerRoutine(int iSignal)
  1186. {
  1187. if (SysBreakHandler != NULL)
  1188. SysBreakHandler();
  1189. SysSetSignal(iSignal, SysBreakHandlerRoutine);
  1190. }
  1191. void SysSetBreakHandler(void (*BreakHandler) (void))
  1192. {
  1193. SysBreakHandler = BreakHandler;
  1194. ///////////////////////////////////////////////////////////////////////////////
  1195. //  Setup signal handlers and enable signals
  1196. ///////////////////////////////////////////////////////////////////////////////
  1197. SysSetSignal(SIGINT, SysBreakHandlerRoutine);
  1198. SysSetSignal(SIGHUP, SysBreakHandlerRoutine);
  1199. sigset_t SigMask;
  1200. sigemptyset(&SigMask);
  1201. sigaddset(&SigMask, SIGINT);
  1202. sigaddset(&SigMask, SIGHUP);
  1203. pthread_sigmask(SIG_UNBLOCK, &SigMask, NULL);
  1204. }
  1205. int SysCreateTlsKey(SYS_TLSKEY & TlsKey, void (*pFreeProc) (void *))
  1206. {
  1207. if (pthread_key_create(&TlsKey, pFreeProc) != 0) {
  1208. ErrSetErrorCode(ERR_NOMORE_TLSKEYS);
  1209. return (ERR_NOMORE_TLSKEYS);
  1210. }
  1211. return (0);
  1212. }
  1213. int SysDeleteTlsKey(SYS_TLSKEY & TlsKey)
  1214. {
  1215. pthread_key_delete(TlsKey);
  1216. return (0);
  1217. }
  1218. int SysSetTlsKeyData(SYS_TLSKEY & TlsKey, void *pData)
  1219. {
  1220. if (pthread_setspecific(TlsKey, pData) != 0) {
  1221. ErrSetErrorCode(ERR_INVALID_TLSKEY);
  1222. return (ERR_INVALID_TLSKEY);
  1223. }
  1224. return (0);
  1225. }
  1226. void *SysGetTlsKeyData(SYS_TLSKEY & TlsKey)
  1227. {
  1228. return (pthread_getspecific(TlsKey));
  1229. }
  1230. void SysThreadOnce(SYS_THREAD_ONCE * pThrOnce, void (*pOnceProc) (void))
  1231. {
  1232. pthread_once(pThrOnce, pOnceProc);
  1233. }
  1234. void *SysAlloc(unsigned int uSize)
  1235. {
  1236. void *pData = malloc(uSize);
  1237. if (pData != NULL)
  1238. memset(pData, 0, uSize);
  1239. else
  1240. ErrSetErrorCode(ERR_MEMORY);
  1241. return (pData);
  1242. }
  1243. void SysFree(void *pData)
  1244. {
  1245. free(pData);
  1246. }
  1247. void *SysRealloc(void *pData, unsigned int uSize)
  1248. {
  1249. void *pNewData = realloc(pData, uSize);
  1250. if (pNewData == NULL)
  1251. ErrSetErrorCode(ERR_MEMORY);
  1252. return (pNewData);
  1253. }
  1254. int SysLockFile(const char *pszFileName, char const *pszLockExt)
  1255. {
  1256. char szLockFile[SYS_MAX_PATH] = "";
  1257. snprintf(szLockFile, sizeof(szLockFile) - 1, "%s%s", pszFileName, pszLockExt);
  1258. int iFileID = open(szLockFile, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
  1259. if (iFileID == -1) {
  1260. ErrSetErrorCode(ERR_LOCKED);
  1261. return (ERR_LOCKED);
  1262. }
  1263. char szLock[128] = "";
  1264. sprintf(szLock, "%lu", (unsigned long) SysGetCurrentThreadId());
  1265. write(iFileID, szLock, strlen(szLock) + 1);
  1266. close(iFileID);
  1267. return (0);
  1268. }
  1269. int SysUnlockFile(const char *pszFileName, char const *pszLockExt)
  1270. {
  1271. char szLockFile[SYS_MAX_PATH] = "";
  1272. snprintf(szLockFile, sizeof(szLockFile) - 1, "%s%s", pszFileName, pszLockExt);
  1273. if (unlink(szLockFile) != 0) {
  1274. ErrSetErrorCode(ERR_NOT_LOCKED);
  1275. return (ERR_NOT_LOCKED);
  1276. }
  1277. return (0);
  1278. }
  1279. SYS_HANDLE SysOpenModule(char const *pszFilePath)
  1280. {
  1281. void *pModule = dlopen(pszFilePath, RTLD_LAZY);
  1282. if (pModule == NULL) {
  1283. ErrSetErrorCode(ERR_LOADMODULE, pszFilePath);
  1284. return (SYS_INVALID_HANDLE);
  1285. }
  1286. return ((SYS_HANDLE) pModule);
  1287. }
  1288. int SysCloseModule(SYS_HANDLE hModule)
  1289. {
  1290. dlclose((void *) hModule);
  1291. return (0);
  1292. }
  1293. void *SysGetSymbol(SYS_HANDLE hModule, char const *pszSymbol)
  1294. {
  1295. void *pSymbol = dlsym((void *) hModule, pszSymbol);
  1296. if (pSymbol == NULL) {
  1297. ErrSetErrorCode(ERR_LOADMODULESYMBOL, pszSymbol);
  1298. return (NULL);
  1299. }
  1300. return (pSymbol);
  1301. }
  1302. int SysEventLogV(int iLogLevel, char const *pszFormat, va_list Args)
  1303. {
  1304. openlog(APP_NAME_STR, LOG_PID, LOG_DAEMON);
  1305. char szBuffer[2048] = "";
  1306. vsnprintf(szBuffer, sizeof(szBuffer) - 1, pszFormat, Args);
  1307. syslog(LOG_DAEMON | LOG_ERR, "%s", szBuffer);
  1308. closelog();
  1309. return (0);
  1310. }
  1311. int SysEventLog(int iLogLevel, char const *pszFormat, ...)
  1312. {
  1313. va_list Args;
  1314. va_start(Args, pszFormat);
  1315. int iLogResult = SysEventLogV(iLogLevel, pszFormat, Args);
  1316. va_end(Args);
  1317. return (0);
  1318. }
  1319. int SysLogMessage(int iLogLevel, char const *pszFormat, ...)
  1320. {
  1321. extern bool bServerDebug;
  1322. pthread_mutex_lock(&LogMutex);
  1323. va_list Args;
  1324. va_start(Args, pszFormat);
  1325. if (bServerDebug) {
  1326. ///////////////////////////////////////////////////////////////////////////////
  1327. //  Debug implementation
  1328. ///////////////////////////////////////////////////////////////////////////////
  1329. vprintf(pszFormat, Args);
  1330. } else {
  1331. switch (iLogLevel) {
  1332. case (LOG_LEV_WARNING):
  1333. case (LOG_LEV_ERROR):
  1334. SysEventLogV(iLogLevel, pszFormat, Args);
  1335. break;
  1336. }
  1337. }
  1338. va_end(Args);
  1339. pthread_mutex_unlock(&LogMutex);
  1340. return (0);
  1341. }
  1342. void SysSleep(int iTimeout)
  1343. {
  1344. SysMsSleep(iTimeout * 1000);
  1345. }
  1346. static int SysSetupWait(WaitData * pWD)
  1347. {
  1348. if (pthread_mutex_init(&pWD->Mtx, NULL) != 0) {
  1349. ErrSetErrorCode(ERR_MUTEXINIT);
  1350. return (ERR_MUTEXINIT);
  1351. }
  1352. if (pthread_cond_init(&pWD->WaitCond, NULL) != 0) {
  1353. pthread_mutex_destroy(&pWD->Mtx);
  1354. ErrSetErrorCode(ERR_CONDINIT);
  1355. return (ERR_CONDINIT);
  1356. }
  1357. return (0);
  1358. }
  1359. static int SysWait(WaitData * pWD, int iMsTimeout)
  1360. {
  1361. struct timespec TV;
  1362. struct timeval TmNow;
  1363. int iErrorCode;
  1364. gettimeofday(&TmNow, NULL);
  1365. TmNow.tv_sec += iMsTimeout / 1000;
  1366. TmNow.tv_usec += (iMsTimeout % 1000) * 1000;
  1367. TmNow.tv_sec += TmNow.tv_usec / 1000000;
  1368. TmNow.tv_usec %= 1000000;
  1369. TV.tv_sec = TmNow.tv_sec;
  1370. TV.tv_nsec = TmNow.tv_usec * 1000;
  1371. pthread_mutex_lock(&pWD->Mtx);
  1372. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pWD->Mtx);
  1373. iErrorCode = pthread_cond_timedwait(&pWD->WaitCond, &pWD->Mtx, &TV);
  1374. pthread_cleanup_pop(1);
  1375. if (iErrorCode == ETIMEDOUT) {
  1376. ErrSetErrorCode(ERR_TIMEOUT);
  1377. return (ERR_TIMEOUT);
  1378. }
  1379. return (0);
  1380. }
  1381. static void SysCleanupWait(WaitData * pWD)
  1382. {
  1383. pthread_mutex_destroy(&pWD->Mtx);
  1384. pthread_cond_destroy(&pWD->WaitCond);
  1385. }
  1386. void SysMsSleep(int iMsTimeout)
  1387. {
  1388. WaitData WD;
  1389. if (SysSetupWait(&WD) == 0) {
  1390. SysWait(&WD, iMsTimeout);
  1391. SysCleanupWait(&WD);
  1392. }
  1393. }
  1394. SYS_INT64 SysMsTime(void)
  1395. {
  1396. struct timeval tv;
  1397. if (gettimeofday(&tv, NULL) != 0)
  1398. return (0);
  1399. return (1000 * (SYS_INT64) tv.tv_sec + (SYS_INT64) tv.tv_usec / 1000);
  1400. }
  1401. int SysExistFile(const char *pszFilePath)
  1402. {
  1403. struct stat FS;
  1404. if (stat(pszFilePath, &FS) != 0)
  1405. return (0);
  1406. return ((S_ISDIR(FS.st_mode)) ? 0 : 1);
  1407. }
  1408. int SysExistDir(const char *pszDirPath)
  1409. {
  1410. struct stat FS;
  1411. if (stat(pszDirPath, &FS) != 0)
  1412. return (0);
  1413. return ((S_ISDIR(FS.st_mode)) ? 1 : 0);
  1414. }
  1415. SYS_HANDLE SysFirstFile(const char *pszPath, char *pszFileName)
  1416. {
  1417. DIR *pDIR = opendir(pszPath);
  1418. if (pDIR == NULL) {
  1419. ErrSetErrorCode(ERR_OPENDIR);
  1420. return (SYS_INVALID_HANDLE);
  1421. }
  1422. FilledDirent FDE;
  1423. struct dirent *pDirEntry = NULL;
  1424. readdir_r(pDIR, &FDE.DE, &pDirEntry);
  1425. if (pDirEntry == NULL) {
  1426. closedir(pDIR);
  1427. return (SYS_INVALID_HANDLE);
  1428. }
  1429. FileFindData *pFFD = (FileFindData *) SysAlloc(sizeof(FileFindData));
  1430. if (pFFD == NULL) {
  1431. closedir(pDIR);
  1432. return (SYS_INVALID_HANDLE);
  1433. }
  1434. strcpy(pFFD->szPath, pszPath);
  1435. AppendSlash(pFFD->szPath);
  1436. pFFD->pDIR = pDIR;
  1437. pFFD->FDE = FDE;
  1438. strcpy(pszFileName, pFFD->FDE.DE.d_name);
  1439. char szFilePath[SYS_MAX_PATH] = "";
  1440. snprintf(szFilePath, sizeof(szFilePath) - 1, "%s%s", pFFD->szPath, pFFD->FDE.DE.d_name);
  1441. if (stat(szFilePath, &pFFD->FS) != 0) {
  1442. SysFree(pFFD);
  1443. closedir(pDIR);
  1444. ErrSetErrorCode(ERR_STAT);
  1445. return (SYS_INVALID_HANDLE);
  1446. }
  1447. return ((SYS_HANDLE) pFFD);
  1448. }
  1449. int SysIsDirectory(SYS_HANDLE hFind)
  1450. {
  1451. FileFindData *pFFD = (FileFindData *) hFind;
  1452. return ((S_ISDIR(pFFD->FS.st_mode)) ? 1 : 0);
  1453. }
  1454. unsigned long SysGetSize(SYS_HANDLE hFind)
  1455. {
  1456. FileFindData *pFFD = (FileFindData *) hFind;
  1457. return ((unsigned long) pFFD->FS.st_size);
  1458. }
  1459. int SysNextFile(SYS_HANDLE hFind, char *pszFileName)
  1460. {
  1461. FileFindData *pFFD = (FileFindData *) hFind;
  1462. struct dirent *pDirEntry = NULL;
  1463. readdir_r(pFFD->pDIR, &pFFD->FDE.DE, &pDirEntry);
  1464. if (pDirEntry == NULL)
  1465. return (0);
  1466. strcpy(pszFileName, pFFD->FDE.DE.d_name);
  1467. char szFilePath[SYS_MAX_PATH] = "";
  1468. snprintf(szFilePath, sizeof(szFilePath) - 1, "%s%s", pFFD->szPath, pFFD->FDE.DE.d_name);
  1469. if (stat(szFilePath, &pFFD->FS) != 0) {
  1470. ErrSetErrorCode(ERR_STAT);
  1471. return (0);
  1472. }
  1473. return (1);
  1474. }
  1475. void SysFindClose(SYS_HANDLE hFind)
  1476. {
  1477. FileFindData *pFFD = (FileFindData *) hFind;
  1478. closedir(pFFD->pDIR);
  1479. SysFree(pFFD);
  1480. }
  1481. int SysGetFileInfo(char const *pszFileName, SYS_FILE_INFO & FI)
  1482. {
  1483. struct stat stat_buffer;
  1484. if (stat(pszFileName, &stat_buffer) != 0) {
  1485. ErrSetErrorCode(ERR_STAT);
  1486. return (ERR_STAT);
  1487. }
  1488. ZeroData(FI);
  1489. FI.iFileType = (S_ISREG(stat_buffer.st_mode)) ? ftNormal :
  1490. ((S_ISDIR(stat_buffer.st_mode)) ? ftDirectory :
  1491.  ((S_ISLNK(stat_buffer.st_mode)) ? ftLink : ftOther));
  1492. FI.ulSize = (unsigned long) stat_buffer.st_size;
  1493. FI.tMod = stat_buffer.st_mtime;
  1494. return (0);
  1495. }
  1496. int SysSetFileModTime(char const *pszFileName, time_t tMod)
  1497. {
  1498. struct utimbuf TMB;
  1499. TMB.actime = tMod;
  1500. TMB.modtime = tMod;
  1501. if (utime(pszFileName, &TMB) != 0) {
  1502. ErrSetErrorCode(ERR_SET_FILE_TIME);
  1503. return (ERR_SET_FILE_TIME);
  1504. }
  1505. return (0);
  1506. }
  1507. char *SysStrDup(const char *pszString)
  1508. {
  1509. int iStrLength = strlen(pszString);
  1510. char *pszBuffer = (char *) SysAlloc(iStrLength + 1);
  1511. if (pszBuffer != NULL)
  1512. strcpy(pszBuffer, pszString);
  1513. return (pszBuffer);
  1514. }
  1515. char *SysGetEnv(const char *pszVarName)
  1516. {
  1517. const char *pszValue = getenv(pszVarName);
  1518. return ((pszValue != NULL) ? SysStrDup(pszValue) : NULL);
  1519. }
  1520. char *SysGetTmpFile(char *pszFileName)
  1521. {
  1522. static unsigned long ulFileSeqNr = 0;
  1523. unsigned long ulThreadID = SysGetCurrentThreadId();
  1524. sprintf(pszFileName, "/tmp/msrv%lx.%lx.tmp", ulThreadID, ulFileSeqNr++);
  1525. return (pszFileName);
  1526. }
  1527. int SysRemove(const char *pszFileName)
  1528. {
  1529. if (unlink(pszFileName) != 0) {
  1530. ErrSetErrorCode(ERR_FILE_DELETE);
  1531. return (ERR_FILE_DELETE);
  1532. }
  1533. return (0);
  1534. }
  1535. int SysMakeDir(const char *pszPath)
  1536. {
  1537. if (mkdir(pszPath, 0700) != 0) {
  1538. ErrSetErrorCode(ERR_DIR_CREATE);
  1539. return (ERR_DIR_CREATE);
  1540. }
  1541. return (0);
  1542. }
  1543. int SysRemoveDir(const char *pszPath)
  1544. {
  1545. if (rmdir(pszPath) != 0) {
  1546. ErrSetErrorCode(ERR_DIR_DELETE);
  1547. return (ERR_DIR_DELETE);
  1548. }
  1549. return (0);
  1550. }
  1551. int SysMoveFile(char const *pszOldName, char const *pszNewName)
  1552. {
  1553. if (rename(pszOldName, pszNewName) != 0) {
  1554. ErrSetErrorCode(ERR_FILE_MOVE);
  1555. return (ERR_FILE_MOVE);
  1556. }
  1557. return (0);
  1558. }
  1559. int SysVSNPrintf(char *pszBuffer, int iSize, char const *pszFormat, va_list Args)
  1560. {
  1561. int iPrintResult = vsnprintf(pszBuffer, iSize, pszFormat, Args);
  1562. return ((iPrintResult < iSize) ? iPrintResult : -1);
  1563. }
  1564. int SysFileSync(FILE * pFile)
  1565. {
  1566. if (fflush(pFile) || fsync(fileno(pFile))) {
  1567. ErrSetErrorCode(ERR_FILE_WRITE);
  1568. return (ERR_FILE_WRITE);
  1569. }
  1570. return (0);
  1571. }
  1572. char *SysStrTok(char *pszData, char const *pszDelim, char **ppszSavePtr)
  1573. {
  1574. return (strtok_r(pszData, pszDelim, ppszSavePtr));
  1575. }
  1576. char *SysCTime(time_t * pTimer, char *pszBuffer, int iBufferSize)
  1577. {
  1578. return (ctime_r(pTimer, pszBuffer));
  1579. }
  1580. struct tm *SysLocalTime(time_t * pTimer, struct tm *pTStruct)
  1581. {
  1582. return (localtime_r(pTimer, pTStruct));
  1583. }
  1584. struct tm *SysGMTime(time_t * pTimer, struct tm *pTStruct)
  1585. {
  1586. return (gmtime_r(pTimer, pTStruct));
  1587. }
  1588. char *SysAscTime(struct tm *pTStruct, char *pszBuffer, int iBufferSize)
  1589. {
  1590. return (asctime_r(pTStruct, pszBuffer));
  1591. }
  1592. long SysGetTimeZone(void)
  1593. {
  1594. time_t tCurr = time(NULL);
  1595. struct tm tmCurr;
  1596. localtime_r(&tCurr, &tmCurr);
  1597. return ((long) -tmCurr.tm_gmtoff);
  1598. }
  1599. long SysGetDayLight(void)
  1600. {
  1601. time_t tCurr = time(NULL);
  1602. struct tm tmCurr;
  1603. localtime_r(&tCurr, &tmCurr);
  1604. return ((long) ((tmCurr.tm_isdst <= 0) ? 0 : 3600));
  1605. }
  1606. int SysGetDiskSpace(char const *pszPath, SYS_INT64 * pTotal, SYS_INT64 * pFree)
  1607. {
  1608. struct statfs SFS;
  1609. if (statfs(pszPath, &SFS) != 0) {
  1610. ErrSetErrorCode(ERR_GET_DISK_SPACE_INFO);
  1611. return (ERR_GET_DISK_SPACE_INFO);
  1612. }
  1613. *pTotal = (SYS_INT64) SFS.f_bsize * (SYS_INT64) SFS.f_blocks;
  1614. *pFree = (SYS_INT64) SFS.f_bsize * (SYS_INT64) SFS.f_bavail;
  1615. return (0);
  1616. }
  1617. int SysMemoryInfo(SYS_INT64 * pRamTotal, SYS_INT64 * pRamFree,
  1618.   SYS_INT64 * pVirtTotal, SYS_INT64 * pVirtFree)
  1619. {
  1620. #if defined(__FREEBSD__)
  1621. int iValue;
  1622. size_t DataLen;
  1623. DataLen = sizeof(iValue);
  1624. if (sysctlbyname("vm.stats.vm.v_page_size", &iValue, &DataLen, NULL, 0) != 0) {
  1625. ErrSetErrorCode(ERR_GET_MEMORY_INFO);
  1626. return (ERR_GET_MEMORY_INFO);
  1627. }
  1628. SYS_INT64 PageSize = (SYS_INT64) iValue;
  1629. DataLen = sizeof(iValue);
  1630. if (sysctlbyname("vm.stats.vm.v_page_count", &iValue, &DataLen, NULL, 0) != 0) {
  1631. ErrSetErrorCode(ERR_GET_MEMORY_INFO);
  1632. return (ERR_GET_MEMORY_INFO);
  1633. }
  1634. *pVirtTotal = *pRamTotal = (SYS_INT64) iValue *PageSize;
  1635. DataLen = sizeof(iValue);
  1636. if (sysctlbyname("vm.stats.vm.v_free_count", &iValue, &DataLen, NULL, 0) != 0) {
  1637. ErrSetErrorCode(ERR_GET_MEMORY_INFO);
  1638. return (ERR_GET_MEMORY_INFO);
  1639. }
  1640. *pVirtFree = *pRamFree = (SYS_INT64) iValue *PageSize;
  1641. ///////////////////////////////////////////////////////////////////////////////
  1642. //  Get swap infos through the kvm interface
  1643. ///////////////////////////////////////////////////////////////////////////////
  1644. char szErrBuffer[_POSIX2_LINE_MAX] = "";
  1645. kvm_t *pKD = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, szErrBuffer);
  1646. if (pKD == NULL) {
  1647. ErrSetErrorCode(ERR_GET_MEMORY_INFO);
  1648. return (ERR_GET_MEMORY_INFO);
  1649. }
  1650. struct kvm_swap KSwap[8];
  1651. int iSwaps = kvm_getswapinfo(pKD, KSwap, CountOf(KSwap), SWIF_DEV_PREFIX);
  1652. for (int ii; ii < iSwaps; ii++) {
  1653. *pVirtFree += (SYS_INT64) (KSwap[ii].ksw_total - KSwap[ii].ksw_used) * PageSize;
  1654. *pVirtTotal += (SYS_INT64) KSwap[ii].ksw_total * PageSize;
  1655. }
  1656. kvm_close(pKD);
  1657. return (0);
  1658. #else // #if defined(__FREEBSD__)
  1659. int iResult = 0, iHwPhisMem, iHwPageSize;
  1660. size_t DataLen;
  1661. struct vmtotal VmMeter;
  1662. static int iHwPhisMem_mib[] = { CTL_HW, HW_PHYSMEM };
  1663. static int iHwPageSize_mib[] = { CTL_HW, HW_PAGESIZE };
  1664. static int VmMeter_mib[] = { CTL_VM, VM_METER };
  1665. DataLen = sizeof(iHwPhisMem);
  1666. if (iResult >= 0)
  1667. iResult = sysctl(iHwPhisMem_mib, 2, &iHwPhisMem, &DataLen, NULL, 0);
  1668. DataLen = sizeof(iHwPageSize);
  1669. if (iResult >= 0)
  1670. iResult = sysctl(iHwPageSize_mib, 2, &iHwPageSize, &DataLen, NULL, 0);
  1671. DataLen = sizeof(vmtotal);
  1672. if (iResult >= 0)
  1673. iResult = sysctl(VmMeter_mib, 2, &VmMeter, &DataLen, NULL, 0);
  1674. if (iResult < 0) {
  1675. ErrSetErrorCode(ERR_GET_MEMORY_INFO);
  1676. return (ERR_GET_MEMORY_INFO);
  1677. }
  1678. *pRamTotal = iHwPhisMem;
  1679. *pRamFree = (SYS_INT64) iHwPageSize *(SYS_INT64) VmMeter.t_free;
  1680. *pVirtTotal = (SYS_INT64) iHwPageSize *(SYS_INT64) VmMeter.t_vm;
  1681. *pVirtFree = *pVirtTotal - (SYS_INT64) iHwPageSize *(SYS_INT64) VmMeter.t_avm;
  1682. return (0);
  1683. #endif // #if defined(__FREEBSD__)
  1684. }
  1685. static unsigned int SysStkCall(unsigned int (*pProc) (void *), void *pData)
  1686. {
  1687. srand(getpid() * (unsigned int) time(NULL) * uSRandBase);
  1688. unsigned int uResult;
  1689. unsigned int uStkDisp =
  1690. (unsigned int) (rand() % MAX_STACK_SHIFT) & ~(STACK_ALIGN_BYTES - 1);
  1691. void *pStkSpace = alloca(uStkDisp);
  1692. uResult = pProc(pData);
  1693. return (uResult);
  1694. }