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

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