SysDepSolaris.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 MAX_THREAD_CONCURRENCY      512
  27. #define SHUTDOWN_RECV_TIMEOUT       2
  28. #define SAIN_Addr(s)                (s).sin_addr.s_addr
  29. #define SCHED_PRIORITY_INC          5
  30. #define MIN_TCP_SEND_SIZE           (1024 * 8)
  31. #define MAX_TCP_SEND_SIZE           (1024 * 128)
  32. #define K_IO_TIME_RATIO             8
  33. #define MAX_SWAP_NAME_SIZE          256
  34. #define WAIT_PID_TIME_STEP          250
  35. #define WAIT_TIMEO_EXIT_STATUS      255
  36. #define WAIT_ERROR_EXIT_STATUS      254
  37. #define MAX_STACK_SHIFT             2048
  38. #define STACK_ALIGN_BYTES           sizeof(int)
  39. struct SemData {
  40. pthread_mutex_t Mtx;
  41. pthread_cond_t WaitCond;
  42. int iSemCounter;
  43. int iMaxCount;
  44. };
  45. struct MutexData {
  46. pthread_mutex_t Mtx;
  47. pthread_cond_t WaitCond;
  48. int iLocked;
  49. };
  50. struct EventData {
  51. pthread_mutex_t Mtx;
  52. pthread_cond_t WaitCond;
  53. int iSignaled;
  54. int iManualReset;
  55. };
  56. struct WaitData {
  57. pthread_mutex_t Mtx;
  58. pthread_cond_t WaitCond;
  59. };
  60. struct ThrData {
  61. pthread_t ThreadId;
  62. unsigned int (*ThreadProc) (void *);
  63. void *pThreadData;
  64. pthread_mutex_t Mtx;
  65. pthread_cond_t ExitWaitCond;
  66. int iThreadEnded;
  67. int iExitCode;
  68. int iUseCount;
  69. };
  70. union FilledDirent {
  71. struct dirent DE;
  72. char Pad[sizeof(struct dirent) + NAME_MAX];
  73. };
  74. struct FileFindData {
  75. char szPath[SYS_MAX_PATH];
  76. DIR *pDIR;
  77. FilledDirent FDE;
  78. struct stat FS;
  79. };
  80. static int SysSetSignal(int iSigNo, void (*pSigProc) (int));
  81. static char const *SysGetLastError(void);
  82. static void SysIgnoreProc(int iSignal);
  83. static int SysSetSockNoDelay(SYS_SOCKET SockFD, int iNoDelay);
  84. static int SysSetSocketsOptions(SYS_SOCKET SockFD);
  85. static int SysFreeThreadData(ThrData * pTD);
  86. static void *SysThreadStartup(void *pThreadData);
  87. static int SysThreadSetup(ThrData * pTD);
  88. static void SysThreadCleanup(ThrData * pTD);
  89. static int SysSafeMsSleep(int iMsTimeout);
  90. static int SysWaitPID(pid_t PID, int *piExitCode, int iTimeout);
  91. static void SysBreakHandlerRoutine(int iSignal);
  92. static int SysSetupWait(WaitData * pWD);
  93. static int SysWait(WaitData * pWD, int iMsTimeout);
  94. static void SysCleanupWait(WaitData * pWD);
  95. static int SysGetSwapInfo(SYS_INT64 * pSwapTotal, SYS_INT64 * pSwapFree);
  96. static unsigned int SysStkCall(unsigned int (*pProc) (void *), void *pData);
  97. static volatile int iShutDown = 0;
  98. static unsigned int uSRandBase;
  99. static pthread_mutex_t LogMutex = PTHREAD_MUTEX_INITIALIZER;
  100. static void (*SysBreakHandler) (void) = NULL;
  101. static int iSndBufSize = -1, iRcvBufSize = -1;
  102. static int SysSetSignal(int iSigNo, void (*pSigProc) (int))
  103. {
  104. signal(iSigNo, pSigProc);
  105. return (0);
  106. }
  107. static char const *SysGetLastError(void)
  108. {
  109. static char szMessage[1024] = "";
  110. snprintf(szMessage, sizeof(szMessage) - 1, "(0x%lX) %s", (unsigned long) errno,
  111.  strerror(errno));
  112. return (szMessage);
  113. }
  114. static void SysIgnoreProc(int iSignal)
  115. {
  116. SysSetSignal(iSignal, SysIgnoreProc);
  117. }
  118. int SysInitLibrary(void)
  119. {
  120. iShutDown = 0;
  121. tzset();
  122. uSRandBase = (unsigned int) time(NULL);
  123. thr_setconcurrency(MAX_THREAD_CONCURRENCY);
  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. int iErrorNo = 0;
  503. struct hostent HostEnt;
  504. char szBuffer[1024];
  505. struct hostent *pHostEnt =
  506. gethostbyname_r(pszName, &HostEnt, szBuffer, sizeof(szBuffer), &iErrorNo);
  507. if ((pHostEnt == NULL) || (pHostEnt->h_addr_list[0] == NULL)) {
  508. ErrSetErrorCode(ERR_BAD_SERVER_ADDR, pszName);
  509. return (ERR_BAD_SERVER_ADDR);
  510. }
  511. memcpy(&NetAddr, pHostEnt->h_addr_list[0], sizeof(NetAddr));
  512. return (0);
  513. }
  514. int SysGetHostByAddr(SYS_INET_ADDR const &AddrInfo, char *pszFQDN)
  515. {
  516. int iErrorNo = 0;
  517. struct hostent HostEnt;
  518. char szBuffer[1024];
  519. struct hostent *pHostEnt = gethostbyaddr_r((const char *) &SAIN_Addr(AddrInfo.Addr),
  520.    sizeof(SAIN_Addr(AddrInfo.Addr)), AF_INET,
  521.    &HostEnt, szBuffer, sizeof(szBuffer),
  522.    &iErrorNo);
  523. if ((pHostEnt == NULL) || (pHostEnt->h_name == NULL)) {
  524. char szIP[128] = "???.???.???.???";
  525. ErrSetErrorCode(ERR_GET_SOCK_HOST, SysInetNToA(AddrInfo, szIP));
  526. return (ERR_GET_SOCK_HOST);
  527. }
  528. strcpy(pszFQDN, pHostEnt->h_name);
  529. return (0);
  530. }
  531. int SysGetPeerInfo(SYS_SOCKET SockFD, SYS_INET_ADDR & AddrInfo)
  532. {
  533. ZeroData(AddrInfo);
  534. socklen_t InfoSize = sizeof(AddrInfo.Addr);
  535. if (getpeername(SockFD, (struct sockaddr *) &AddrInfo.Addr, &InfoSize) == -1) {
  536. ErrSetErrorCode(ERR_GET_PEER_INFO);
  537. return (ERR_GET_PEER_INFO);
  538. }
  539. return (0);
  540. }
  541. int SysGetSockInfo(SYS_SOCKET SockFD, SYS_INET_ADDR & AddrInfo)
  542. {
  543. ZeroData(AddrInfo);
  544. socklen_t InfoSize = sizeof(AddrInfo.Addr);
  545. if (getsockname(SockFD, (struct sockaddr *) &AddrInfo.Addr, &InfoSize) == -1) {
  546. ErrSetErrorCode(ERR_GET_SOCK_INFO);
  547. return (ERR_GET_SOCK_INFO);
  548. }
  549. return (0);
  550. }
  551. char *SysInetNToA(SYS_INET_ADDR const &AddrInfo, char *pszIP)
  552. {
  553. union {
  554. unsigned int a;
  555. unsigned char b[4];
  556. } UAddr;
  557. memcpy(&UAddr, &AddrInfo.Addr.sin_addr, sizeof(UAddr));
  558. sprintf(pszIP, "%u.%u.%u.%u",
  559. (unsigned int) UAddr.b[0],
  560. (unsigned int) UAddr.b[1], (unsigned int) UAddr.b[2], (unsigned int) UAddr.b[3]);
  561. return (pszIP);
  562. }
  563. int SysInetAddr(char const *pszDotName, NET_ADDRESS & NetAddr)
  564. {
  565. if ((NetAddr = (NET_ADDRESS) inet_addr(pszDotName)) == SYS_INVALID_NET_ADDRESS) {
  566. ErrSetErrorCode(ERR_BAD_SERVER_ADDR, pszDotName);
  567. return (ERR_BAD_SERVER_ADDR);
  568. }
  569. return (0);
  570. }
  571. int SysSameAddress(NET_ADDRESS const &NetAddr1, NET_ADDRESS const &NetAddr2)
  572. {
  573. return (memcmp(&NetAddr1, &NetAddr2, sizeof(NET_ADDRESS)) == 0);
  574. }
  575. SYS_SEMAPHORE SysCreateSemaphore(int iInitCount, int iMaxCount)
  576. {
  577. SemData *pSD = (SemData *) SysAlloc(sizeof(SemData));
  578. if (pSD == NULL)
  579. return (SYS_INVALID_SEMAPHORE);
  580. if (pthread_mutex_init(&pSD->Mtx, NULL) != 0) {
  581. SysFree(pSD);
  582. ErrSetErrorCode(ERR_MUTEXINIT, NULL);
  583. return (SYS_INVALID_SEMAPHORE);
  584. }
  585. if (pthread_cond_init(&pSD->WaitCond, NULL) != 0) {
  586. pthread_mutex_destroy(&pSD->Mtx);
  587. SysFree(pSD);
  588. ErrSetErrorCode(ERR_CONDINIT, NULL);
  589. return (SYS_INVALID_SEMAPHORE);
  590. }
  591. pSD->iSemCounter = iInitCount;
  592. pSD->iMaxCount = iMaxCount;
  593. return ((SYS_SEMAPHORE) pSD);
  594. }
  595. int SysCloseSemaphore(SYS_SEMAPHORE hSemaphore)
  596. {
  597. SemData *pSD = (SemData *) hSemaphore;
  598. pthread_cond_destroy(&pSD->WaitCond);
  599. pthread_mutex_destroy(&pSD->Mtx);
  600. SysFree(pSD);
  601. return (0);
  602. }
  603. int SysWaitSemaphore(SYS_SEMAPHORE hSemaphore, int iTimeout)
  604. {
  605. SemData *pSD = (SemData *) hSemaphore;
  606. pthread_mutex_lock(&pSD->Mtx);
  607. if (iTimeout == SYS_INFINITE_TIMEOUT) {
  608. while (pSD->iSemCounter <= 0) {
  609. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pSD->Mtx);
  610. pthread_cond_wait(&pSD->WaitCond, &pSD->Mtx);
  611. pthread_cleanup_pop(0);
  612. }
  613. pSD->iSemCounter -= 1;
  614. } else {
  615. struct timeval tvNow;
  616. struct timespec tsTimeout;
  617. gettimeofday(&tvNow, NULL);
  618. tsTimeout.tv_sec = tvNow.tv_sec + iTimeout;
  619. tsTimeout.tv_nsec = tvNow.tv_usec * 1000;
  620. int iRetCode = 0;
  621. while ((pSD->iSemCounter <= 0) && (iRetCode != ETIMEDOUT)) {
  622. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pSD->Mtx);
  623. iRetCode = pthread_cond_timedwait(&pSD->WaitCond, &pSD->Mtx, &tsTimeout);
  624. pthread_cleanup_pop(0);
  625. }
  626. if (iRetCode == ETIMEDOUT) {
  627. pthread_mutex_unlock(&pSD->Mtx);
  628. ErrSetErrorCode(ERR_TIMEOUT);
  629. return (ERR_TIMEOUT);
  630. }
  631. pSD->iSemCounter -= 1;
  632. }
  633. pthread_mutex_unlock(&pSD->Mtx);
  634. return (0);
  635. }
  636. int SysReleaseSemaphore(SYS_SEMAPHORE hSemaphore, int iCount)
  637. {
  638. SemData *pSD = (SemData *) hSemaphore;
  639. pthread_mutex_lock(&pSD->Mtx);
  640. pSD->iSemCounter += iCount;
  641. if (pSD->iSemCounter > 0) {
  642. if (pSD->iSemCounter > 1)
  643. pthread_cond_broadcast(&pSD->WaitCond);
  644. else
  645. pthread_cond_signal(&pSD->WaitCond);
  646. }
  647. pthread_mutex_unlock(&pSD->Mtx);
  648. return (0);
  649. }
  650. int SysTryWaitSemaphore(SYS_SEMAPHORE hSemaphore)
  651. {
  652. SemData *pSD = (SemData *) hSemaphore;
  653. pthread_mutex_lock(&pSD->Mtx);
  654. if (pSD->iSemCounter <= 0) {
  655. pthread_mutex_unlock(&pSD->Mtx);
  656. ErrSetErrorCode(ERR_TIMEOUT);
  657. return (ERR_TIMEOUT);
  658. }
  659. pSD->iSemCounter -= 1;
  660. pthread_mutex_unlock(&pSD->Mtx);
  661. return (0);
  662. }
  663. SYS_MUTEX SysCreateMutex(void)
  664. {
  665. MutexData *pMD = (MutexData *) SysAlloc(sizeof(MutexData));
  666. if (pMD == NULL)
  667. return (SYS_INVALID_MUTEX);
  668. if (pthread_mutex_init(&pMD->Mtx, NULL) != 0) {
  669. SysFree(pMD);
  670. ErrSetErrorCode(ERR_MUTEXINIT);
  671. return (SYS_INVALID_MUTEX);
  672. }
  673. if (pthread_cond_init(&pMD->WaitCond, NULL) != 0) {
  674. pthread_mutex_destroy(&pMD->Mtx);
  675. SysFree(pMD);
  676. ErrSetErrorCode(ERR_CONDINIT);
  677. return (SYS_INVALID_MUTEX);
  678. }
  679. pMD->iLocked = 0;
  680. return ((SYS_MUTEX) pMD);
  681. }
  682. int SysCloseMutex(SYS_MUTEX hMutex)
  683. {
  684. MutexData *pMD = (MutexData *) hMutex;
  685. pthread_cond_destroy(&pMD->WaitCond);
  686. pthread_mutex_destroy(&pMD->Mtx);
  687. SysFree(pMD);
  688. return (0);
  689. }
  690. int SysLockMutex(SYS_MUTEX hMutex, int iTimeout)
  691. {
  692. MutexData *pMD = (MutexData *) hMutex;
  693. pthread_mutex_lock(&pMD->Mtx);
  694. if (iTimeout == SYS_INFINITE_TIMEOUT) {
  695. while (pMD->iLocked) {
  696. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pMD->Mtx);
  697. pthread_cond_wait(&pMD->WaitCond, &pMD->Mtx);
  698. pthread_cleanup_pop(0);
  699. }
  700. pMD->iLocked = 1;
  701. } else {
  702. struct timeval tvNow;
  703. struct timespec tsTimeout;
  704. gettimeofday(&tvNow, NULL);
  705. tsTimeout.tv_sec = tvNow.tv_sec + iTimeout;
  706. tsTimeout.tv_nsec = tvNow.tv_usec * 1000;
  707. int iRetCode = 0;
  708. while (pMD->iLocked && (iRetCode != ETIMEDOUT)) {
  709. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pMD->Mtx);
  710. iRetCode = pthread_cond_timedwait(&pMD->WaitCond, &pMD->Mtx, &tsTimeout);
  711. pthread_cleanup_pop(0);
  712. }
  713. if (iRetCode == ETIMEDOUT) {
  714. pthread_mutex_unlock(&pMD->Mtx);
  715. ErrSetErrorCode(ERR_TIMEOUT);
  716. return (ERR_TIMEOUT);
  717. }
  718. pMD->iLocked = 1;
  719. }
  720. pthread_mutex_unlock(&pMD->Mtx);
  721. return (0);
  722. }
  723. int SysUnlockMutex(SYS_MUTEX hMutex)
  724. {
  725. MutexData *pMD = (MutexData *) hMutex;
  726. pthread_mutex_lock(&pMD->Mtx);
  727. pMD->iLocked = 0;
  728. pthread_cond_signal(&pMD->WaitCond);
  729. pthread_mutex_unlock(&pMD->Mtx);
  730. return (0);
  731. }
  732. int SysTryLockMutex(SYS_MUTEX hMutex)
  733. {
  734. MutexData *pMD = (MutexData *) hMutex;
  735. pthread_mutex_lock(&pMD->Mtx);
  736. if (pMD->iLocked) {
  737. pthread_mutex_unlock(&pMD->Mtx);
  738. ErrSetErrorCode(ERR_TIMEOUT);
  739. return (-1);
  740. }
  741. pMD->iLocked = 1;
  742. pthread_mutex_unlock(&pMD->Mtx);
  743. return (0);
  744. }
  745. SYS_EVENT SysCreateEvent(int iManualReset)
  746. {
  747. EventData *pED = (EventData *) SysAlloc(sizeof(EventData));
  748. if (pED == NULL)
  749. return (SYS_INVALID_EVENT);
  750. if (pthread_mutex_init(&pED->Mtx, NULL) != 0) {
  751. SysFree(pED);
  752. ErrSetErrorCode(ERR_MUTEXINIT);
  753. return (SYS_INVALID_EVENT);
  754. }
  755. if (pthread_cond_init(&pED->WaitCond, NULL) != 0) {
  756. pthread_mutex_destroy(&pED->Mtx);
  757. SysFree(pED);
  758. ErrSetErrorCode(ERR_CONDINIT);
  759. return (SYS_INVALID_EVENT);
  760. }
  761. pED->iSignaled = 0;
  762. pED->iManualReset = iManualReset;
  763. return ((SYS_EVENT) pED);
  764. }
  765. int SysCloseEvent(SYS_EVENT hEvent)
  766. {
  767. EventData *pED = (EventData *) hEvent;
  768. pthread_cond_destroy(&pED->WaitCond);
  769. pthread_mutex_destroy(&pED->Mtx);
  770. SysFree(pED);
  771. return (0);
  772. }
  773. int SysWaitEvent(SYS_EVENT hEvent, int iTimeout)
  774. {
  775. EventData *pED = (EventData *) hEvent;
  776. pthread_mutex_lock(&pED->Mtx);
  777. if (iTimeout == SYS_INFINITE_TIMEOUT) {
  778. while (!pED->iSignaled) {
  779. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pED->Mtx);
  780. pthread_cond_wait(&pED->WaitCond, &pED->Mtx);
  781. pthread_cleanup_pop(0);
  782. }
  783. if (!pED->iManualReset)
  784. pED->iSignaled = 0;
  785. } else {
  786. struct timeval tvNow;
  787. struct timespec tsTimeout;
  788. gettimeofday(&tvNow, NULL);
  789. tsTimeout.tv_sec = tvNow.tv_sec + iTimeout;
  790. tsTimeout.tv_nsec = tvNow.tv_usec * 1000;
  791. int iRetCode = 0;
  792. while (!pED->iSignaled && (iRetCode != ETIMEDOUT)) {
  793. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pED->Mtx);
  794. iRetCode = pthread_cond_timedwait(&pED->WaitCond, &pED->Mtx, &tsTimeout);
  795. pthread_cleanup_pop(0);
  796. }
  797. if (iRetCode == ETIMEDOUT) {
  798. pthread_mutex_unlock(&pED->Mtx);
  799. ErrSetErrorCode(ERR_TIMEOUT);
  800. return (ERR_TIMEOUT);
  801. }
  802. if (!pED->iManualReset)
  803. pED->iSignaled = 0;
  804. }
  805. pthread_mutex_unlock(&pED->Mtx);
  806. return (0);
  807. }
  808. int SysSetEvent(SYS_EVENT hEvent)
  809. {
  810. EventData *pED = (EventData *) hEvent;
  811. pthread_mutex_lock(&pED->Mtx);
  812. pED->iSignaled = 1;
  813. if (pED->iManualReset)
  814. pthread_cond_broadcast(&pED->WaitCond);
  815. else
  816. pthread_cond_signal(&pED->WaitCond);
  817. pthread_mutex_unlock(&pED->Mtx);
  818. return (0);
  819. }
  820. int SysResetEvent(SYS_EVENT hEvent)
  821. {
  822. EventData *pED = (EventData *) hEvent;
  823. pthread_mutex_lock(&pED->Mtx);
  824. pED->iSignaled = 0;
  825. pthread_mutex_unlock(&pED->Mtx);
  826. return (0);
  827. }
  828. int SysTryWaitEvent(SYS_EVENT hEvent)
  829. {
  830. EventData *pED = (EventData *) hEvent;
  831. pthread_mutex_lock(&pED->Mtx);
  832. if (!pED->iSignaled) {
  833. pthread_mutex_unlock(&pED->Mtx);
  834. ErrSetErrorCode(ERR_TIMEOUT);
  835. return (ERR_TIMEOUT);
  836. }
  837. if (!pED->iManualReset)
  838. pED->iSignaled = 0;
  839. pthread_mutex_unlock(&pED->Mtx);
  840. return (0);
  841. }
  842. static int SysFreeThreadData(ThrData * pTD)
  843. {
  844. pthread_cond_destroy(&pTD->ExitWaitCond);
  845. pthread_mutex_destroy(&pTD->Mtx);
  846. SysFree(pTD);
  847. return (0);
  848. }
  849. static void *SysThreadStartup(void *pThreadData)
  850. {
  851. ThrData *pTD = (ThrData *) pThreadData;
  852. SysThreadSetup(pTD);
  853. int iExitCode;
  854. pthread_cleanup_push((void (*)(void *)) SysThreadCleanup, pTD);
  855. pTD->iExitCode = iExitCode = SysStkCall(pTD->ThreadProc, pTD->pThreadData);
  856. pthread_cleanup_pop(1);
  857. return ((void *) iExitCode);
  858. }
  859. SYS_THREAD SysCreateThread(unsigned int (*pThreadProc) (void *), void *pThreadData)
  860. {
  861. ThrData *pTD = (ThrData *) SysAlloc(sizeof(ThrData));
  862. if (pTD == NULL)
  863. return (SYS_INVALID_THREAD);
  864. pTD->ThreadProc = pThreadProc;
  865. pTD->pThreadData = pThreadData;
  866. pTD->iThreadEnded = 0;
  867. pTD->iExitCode = -1;
  868. pTD->iUseCount = 2;
  869. if (pthread_mutex_init(&pTD->Mtx, NULL) != 0) {
  870. SysFree(pTD);
  871. ErrSetErrorCode(ERR_MUTEXINIT);
  872. return (SYS_INVALID_THREAD);
  873. }
  874. if (pthread_cond_init(&pTD->ExitWaitCond, NULL) != 0) {
  875. pthread_mutex_destroy(&pTD->Mtx);
  876. SysFree(pTD);
  877. ErrSetErrorCode(ERR_CONDINIT);
  878. return (SYS_INVALID_THREAD);
  879. }
  880. pthread_attr_t ThrAttr;
  881. pthread_attr_init(&ThrAttr);
  882. pthread_attr_setscope(&ThrAttr, PTHREAD_SCOPE_SYSTEM);
  883. if (pthread_create(&pTD->ThreadId, &ThrAttr, SysThreadStartup, pTD) != 0) {
  884. pthread_attr_destroy(&ThrAttr);
  885. pthread_cond_destroy(&pTD->ExitWaitCond);
  886. pthread_mutex_destroy(&pTD->Mtx);
  887. SysFree(pTD);
  888. ErrSetErrorCode(ERR_THREADCREATE);
  889. return (SYS_INVALID_THREAD);
  890. }
  891. pthread_attr_destroy(&ThrAttr);
  892. return ((SYS_THREAD) pTD);
  893. }
  894. SYS_THREAD SysCreateServiceThread(unsigned int (*pThreadProc) (void *), SYS_SOCKET SockFD)
  895. {
  896. return (SysCreateThread(pThreadProc, (void *) SockFD));
  897. }
  898. static int SysThreadSetup(ThrData * pTD)
  899. {
  900. sigset_t SigMask;
  901. sigemptyset(&SigMask);
  902. sigaddset(&SigMask, SIGALRM);
  903. sigaddset(&SigMask, SIGINT);
  904. sigaddset(&SigMask, SIGHUP);
  905. sigaddset(&SigMask, SIGSTOP);
  906. sigaddset(&SigMask, SIGCHLD);
  907. pthread_sigmask(SIG_BLOCK, &SigMask, NULL);
  908. sigemptyset(&SigMask);
  909. sigaddset(&SigMask, SIGQUIT);
  910. pthread_sigmask(SIG_UNBLOCK, &SigMask, NULL);
  911. SysSetSignal(SIGQUIT, SysIgnoreProc);
  912. SysSetSignal(SIGPIPE, SysIgnoreProc);
  913. SysSetSignal(SIGCHLD, SysIgnoreProc);
  914. if (pTD != NULL) {
  915. }
  916. return (0);
  917. }
  918. static void SysThreadCleanup(ThrData * pTD)
  919. {
  920. if (pTD != NULL) {
  921. pthread_mutex_lock(&pTD->Mtx);
  922. pTD->iThreadEnded = 1;
  923. pthread_cond_broadcast(&pTD->ExitWaitCond);
  924. if (--pTD->iUseCount == 0) {
  925. pthread_mutex_unlock(&pTD->Mtx);
  926. SysFreeThreadData(pTD);
  927. } else
  928. pthread_mutex_unlock(&pTD->Mtx);
  929. }
  930. }
  931. void SysCloseThread(SYS_THREAD ThreadID, int iForce)
  932. {
  933. ThrData *pTD = (ThrData *) ThreadID;
  934. pthread_mutex_lock(&pTD->Mtx);
  935. pthread_detach(pTD->ThreadId);
  936. if (iForce && !pTD->iThreadEnded)
  937. pthread_cancel(pTD->ThreadId);
  938. if (--pTD->iUseCount == 0) {
  939. pthread_mutex_unlock(&pTD->Mtx);
  940. SysFreeThreadData(pTD);
  941. } else
  942. pthread_mutex_unlock(&pTD->Mtx);
  943. }
  944. int SysSetThreadPriority(SYS_THREAD ThreadID, int iPriority)
  945. {
  946. ThrData *pTD = (ThrData *) ThreadID;
  947. int iPolicy;
  948. struct sched_param SchParam;
  949. if (pthread_getschedparam(pTD->ThreadId, &iPolicy, &SchParam) != 0) {
  950. ErrSetErrorCode(ERR_SET_THREAD_PRIORITY);
  951. return (ERR_SET_THREAD_PRIORITY);
  952. }
  953. int iMinPriority = sched_get_priority_min(iPolicy),
  954. iMaxPriority = sched_get_priority_max(iPolicy),
  955. iStdPriority = (iMinPriority + iMaxPriority) / 2;
  956. switch (iPriority) {
  957. case (SYS_PRIORITY_NORMAL):
  958. SchParam.sched_priority = iStdPriority;
  959. break;
  960. case (SYS_PRIORITY_LOWER):
  961. SchParam.sched_priority = iStdPriority - (iStdPriority - iMinPriority) / 3;
  962. break;
  963. case (SYS_PRIORITY_HIGHER):
  964. SchParam.sched_priority = iStdPriority + (iStdPriority - iMinPriority) / 3;
  965. break;
  966. }
  967. if (pthread_setschedparam(pTD->ThreadId, iPolicy, &SchParam) != 0) {
  968. ErrSetErrorCode(ERR_SET_THREAD_PRIORITY);
  969. return (ERR_SET_THREAD_PRIORITY);
  970. }
  971. return (0);
  972. }
  973. int SysWaitThread(SYS_THREAD ThreadID, int iTimeout)
  974. {
  975. ThrData *pTD = (ThrData *) ThreadID;
  976. pthread_mutex_lock(&pTD->Mtx);
  977. if (iTimeout == SYS_INFINITE_TIMEOUT) {
  978. while (!pTD->iThreadEnded) {
  979. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pTD->Mtx);
  980. pthread_cond_wait(&pTD->ExitWaitCond, &pTD->Mtx);
  981. pthread_cleanup_pop(0);
  982. }
  983. } else {
  984. struct timeval tvNow;
  985. struct timespec tsTimeout;
  986. gettimeofday(&tvNow, NULL);
  987. tsTimeout.tv_sec = tvNow.tv_sec + iTimeout;
  988. tsTimeout.tv_nsec = tvNow.tv_usec * 1000;
  989. int iRetCode = 0;
  990. while (!pTD->iThreadEnded && (iRetCode != ETIMEDOUT)) {
  991. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pTD->Mtx);
  992. iRetCode =
  993. pthread_cond_timedwait(&pTD->ExitWaitCond, &pTD->Mtx, &tsTimeout);
  994. pthread_cleanup_pop(0);
  995. }
  996. if (iRetCode == ETIMEDOUT) {
  997. pthread_mutex_unlock(&pTD->Mtx);
  998. ErrSetErrorCode(ERR_TIMEOUT);
  999. return (ERR_TIMEOUT);
  1000. }
  1001. }
  1002. pthread_mutex_unlock(&pTD->Mtx);
  1003. return (0);
  1004. }
  1005. unsigned long SysGetCurrentThreadId(void)
  1006. {
  1007. return ((unsigned long) pthread_self());
  1008. }
  1009. static int SysSafeMsSleep(int iMsTimeout)
  1010. {
  1011. struct pollfd Dummy;
  1012. ZeroData(Dummy);
  1013. return ((poll(&Dummy, 0, iMsTimeout) == 0) ? 1 : 0);
  1014. }
  1015. static int SysWaitPID(pid_t PID, int *piExitCode, int iTimeout)
  1016. {
  1017. pid_t ExitPID;
  1018. int iExitStatus;
  1019. int iStatus;
  1020. iTimeout *= 1000;
  1021. do {
  1022. if ((ExitPID = (pid_t) waitpid(PID, &iStatus, WNOHANG)) == PID) {
  1023. if (!WIFEXITED(iStatus))
  1024. return (ERR_WAITPID);
  1025. iExitStatus = WEXITSTATUS(iStatus);
  1026. break;
  1027. }
  1028. SysSafeMsSleep(WAIT_PID_TIME_STEP);
  1029. iTimeout -= WAIT_PID_TIME_STEP;
  1030. } while (iTimeout > 0);
  1031. if (PID != ExitPID)
  1032. return (ERR_TIMEOUT);
  1033. if (piExitCode != NULL)
  1034. *piExitCode = iExitStatus;
  1035. return (0);
  1036. }
  1037. int SysExec(char const *pszCommand, char const *const *pszArgs, int iWaitTimeout,
  1038.     int iPriority, int *piExitStatus)
  1039. {
  1040. int iExitStatus;
  1041. pid_t ChildID;
  1042. pid_t ExitPID;
  1043. pid_t ProcessID;
  1044. int iPPipe[2];
  1045. int iCPipe[2];
  1046. if (pipe(iPPipe) == -1) {
  1047. ErrSetErrorCode(ERR_PIPE);
  1048. return (ERR_PIPE);
  1049. }
  1050. if (pipe(iCPipe) == -1) {
  1051. close(iPPipe[1]);
  1052. close(iPPipe[0]);
  1053. ErrSetErrorCode(ERR_PIPE);
  1054. return (ERR_PIPE);
  1055. }
  1056. ProcessID = fork();
  1057. if (ProcessID == 0) {
  1058. ChildID = fork();
  1059. if (ChildID == 0) {
  1060. close(iPPipe[1]);
  1061. close(iPPipe[0]);
  1062. ///////////////////////////////////////////////////////////////////////////////
  1063. //  Wait for the unlock from the parent
  1064. ///////////////////////////////////////////////////////////////////////////////
  1065. read(iCPipe[0], &ChildID, sizeof(ChildID));
  1066. close(iCPipe[1]);
  1067. close(iCPipe[0]);
  1068. ///////////////////////////////////////////////////////////////////////////////
  1069. //  Execute the command
  1070. ///////////////////////////////////////////////////////////////////////////////
  1071. execv(pszCommand, (char **) pszArgs);
  1072. ///////////////////////////////////////////////////////////////////////////////
  1073. //  We can only use async-signal safe functions, so we use write() directly
  1074. ///////////////////////////////////////////////////////////////////////////////
  1075. write(2, "execv error: cmd='", 18);
  1076. write(2, pszCommand, strlen(pszCommand));
  1077. write(2, "'n", 2);
  1078. _exit(WAIT_ERROR_EXIT_STATUS);
  1079. }
  1080. close(iCPipe[1]);
  1081. close(iCPipe[0]);
  1082. ///////////////////////////////////////////////////////////////////////////////
  1083. //  Tell the parent about the child-child PID
  1084. ///////////////////////////////////////////////////////////////////////////////
  1085. write(iPPipe[1], &ChildID, sizeof(ChildID));
  1086. close(iPPipe[1]);
  1087. close(iPPipe[0]);
  1088. if (ChildID == (pid_t) - 1)
  1089. _exit(WAIT_ERROR_EXIT_STATUS);
  1090. ///////////////////////////////////////////////////////////////////////////////
  1091. //  Wait for the child
  1092. ///////////////////////////////////////////////////////////////////////////////
  1093. iExitStatus = WAIT_TIMEO_EXIT_STATUS;
  1094. if (iWaitTimeout > 0)
  1095. SysWaitPID(ChildID, &iExitStatus, iWaitTimeout);
  1096. _exit(iExitStatus);
  1097. }
  1098. if ((ProcessID == (pid_t) - 1) ||
  1099.     (read(iPPipe[0], &ChildID, sizeof(ChildID)) != sizeof(ChildID))) {
  1100. close(iCPipe[1]);
  1101. close(iCPipe[0]);
  1102. close(iPPipe[1]);
  1103. close(iPPipe[0]);
  1104. ErrSetErrorCode(ERR_FORK);
  1105. return (ERR_FORK);
  1106. }
  1107. close(iPPipe[1]);
  1108. close(iPPipe[0]);
  1109. if (ChildID != (pid_t) - 1) {
  1110. ///////////////////////////////////////////////////////////////////////////////
  1111. //  Set process priority
  1112. ///////////////////////////////////////////////////////////////////////////////
  1113. switch (iPriority) {
  1114. case (SYS_PRIORITY_NORMAL):
  1115. setpriority(PRIO_PROCESS, ChildID, 0);
  1116. break;
  1117. case (SYS_PRIORITY_LOWER):
  1118. setpriority(PRIO_PROCESS, ChildID, SCHED_PRIORITY_INC);
  1119. break;
  1120. case (SYS_PRIORITY_HIGHER):
  1121. setpriority(PRIO_PROCESS, ChildID, -SCHED_PRIORITY_INC);
  1122. break;
  1123. }
  1124. ///////////////////////////////////////////////////////////////////////////////
  1125. //  Unlock the child
  1126. ///////////////////////////////////////////////////////////////////////////////
  1127. write(iCPipe[1], &ChildID, sizeof(ChildID));
  1128. }
  1129. close(iCPipe[1]);
  1130. close(iCPipe[0]);
  1131. ///////////////////////////////////////////////////////////////////////////////
  1132. //  Wait for completion (or timeout)
  1133. ///////////////////////////////////////////////////////////////////////////////
  1134. while (((ExitPID = (pid_t) waitpid(ProcessID, &iExitStatus, 0)) != ProcessID) &&
  1135.        (errno == EINTR));
  1136. if ((ExitPID == ProcessID) && WIFEXITED(iExitStatus))
  1137. iExitStatus = WEXITSTATUS(iExitStatus);
  1138. else
  1139. iExitStatus = WAIT_TIMEO_EXIT_STATUS;
  1140. if (iWaitTimeout > 0) {
  1141. if (iExitStatus == WAIT_TIMEO_EXIT_STATUS) {
  1142. ErrSetErrorCode(ERR_TIMEOUT);
  1143. return (ERR_TIMEOUT);
  1144. }
  1145. if (iExitStatus == WAIT_ERROR_EXIT_STATUS) {
  1146. ErrSetErrorCode(ERR_FORK);
  1147. return (ERR_FORK);
  1148. }
  1149. } else
  1150. iExitStatus = -1;
  1151. if (piExitStatus != NULL)
  1152. *piExitStatus = iExitStatus;
  1153. return (0);
  1154. }
  1155. static void SysBreakHandlerRoutine(int iSignal)
  1156. {
  1157. if (SysBreakHandler != NULL)
  1158. SysBreakHandler();
  1159. SysSetSignal(iSignal, SysBreakHandlerRoutine);
  1160. }
  1161. void SysSetBreakHandler(void (*BreakHandler) (void))
  1162. {
  1163. SysBreakHandler = BreakHandler;
  1164. ///////////////////////////////////////////////////////////////////////////////
  1165. //  Setup signal handlers and enable signals
  1166. ///////////////////////////////////////////////////////////////////////////////
  1167. SysSetSignal(SIGINT, SysBreakHandlerRoutine);
  1168. SysSetSignal(SIGHUP, SysBreakHandlerRoutine);
  1169. sigset_t SigMask;
  1170. sigemptyset(&SigMask);
  1171. sigaddset(&SigMask, SIGINT);
  1172. sigaddset(&SigMask, SIGHUP);
  1173. pthread_sigmask(SIG_UNBLOCK, &SigMask, NULL);
  1174. }
  1175. int SysCreateTlsKey(SYS_TLSKEY & TlsKey, void (*pFreeProc) (void *))
  1176. {
  1177. if (pthread_key_create(&TlsKey, pFreeProc) != 0) {
  1178. ErrSetErrorCode(ERR_NOMORE_TLSKEYS);
  1179. return (ERR_NOMORE_TLSKEYS);
  1180. }
  1181. return (0);
  1182. }
  1183. int SysDeleteTlsKey(SYS_TLSKEY & TlsKey)
  1184. {
  1185. pthread_key_delete(TlsKey);
  1186. return (0);
  1187. }
  1188. int SysSetTlsKeyData(SYS_TLSKEY & TlsKey, void *pData)
  1189. {
  1190. if (pthread_setspecific(TlsKey, pData) != 0) {
  1191. ErrSetErrorCode(ERR_INVALID_TLSKEY);
  1192. return (ERR_INVALID_TLSKEY);
  1193. }
  1194. return (0);
  1195. }
  1196. void *SysGetTlsKeyData(SYS_TLSKEY & TlsKey)
  1197. {
  1198. return (pthread_getspecific(TlsKey));
  1199. }
  1200. void SysThreadOnce(SYS_THREAD_ONCE * pThrOnce, void (*pOnceProc) (void))
  1201. {
  1202. pthread_once(pThrOnce, pOnceProc);
  1203. }
  1204. void *SysAlloc(unsigned int uSize)
  1205. {
  1206. void *pData = malloc(uSize);
  1207. if (pData != NULL)
  1208. memset(pData, 0, uSize);
  1209. else
  1210. ErrSetErrorCode(ERR_MEMORY);
  1211. return (pData);
  1212. }
  1213. void SysFree(void *pData)
  1214. {
  1215. free(pData);
  1216. }
  1217. void *SysRealloc(void *pData, unsigned int uSize)
  1218. {
  1219. void *pNewData = realloc(pData, uSize);
  1220. if (pNewData == NULL)
  1221. ErrSetErrorCode(ERR_MEMORY);
  1222. return (pNewData);
  1223. }
  1224. int SysLockFile(const char *pszFileName, char const *pszLockExt)
  1225. {
  1226. char szLockFile[SYS_MAX_PATH] = "";
  1227. snprintf(szLockFile, sizeof(szLockFile) - 1, "%s%s", pszFileName, pszLockExt);
  1228. int iFileID = open(szLockFile, O_CREAT | O_EXCL | O_RDWR, S_IREAD | S_IWRITE);
  1229. if (iFileID == -1) {
  1230. ErrSetErrorCode(ERR_LOCKED);
  1231. return (ERR_LOCKED);
  1232. }
  1233. char szLock[128] = "";
  1234. sprintf(szLock, "%lu", (unsigned long) SysGetCurrentThreadId());
  1235. write(iFileID, szLock, strlen(szLock) + 1);
  1236. close(iFileID);
  1237. return (0);
  1238. }
  1239. int SysUnlockFile(const char *pszFileName, char const *pszLockExt)
  1240. {
  1241. char szLockFile[SYS_MAX_PATH] = "";
  1242. snprintf(szLockFile, sizeof(szLockFile) - 1, "%s%s", pszFileName, pszLockExt);
  1243. if (unlink(szLockFile) != 0) {
  1244. ErrSetErrorCode(ERR_NOT_LOCKED);
  1245. return (ERR_NOT_LOCKED);
  1246. }
  1247. return (0);
  1248. }
  1249. SYS_HANDLE SysOpenModule(char const *pszFilePath)
  1250. {
  1251. void *pModule = dlopen(pszFilePath, RTLD_LAZY);
  1252. if (pModule == NULL) {
  1253. ErrSetErrorCode(ERR_LOADMODULE, pszFilePath);
  1254. return (SYS_INVALID_HANDLE);
  1255. }
  1256. return ((SYS_HANDLE) pModule);
  1257. }
  1258. int SysCloseModule(SYS_HANDLE hModule)
  1259. {
  1260. dlclose((void *) hModule);
  1261. return (0);
  1262. }
  1263. void *SysGetSymbol(SYS_HANDLE hModule, char const *pszSymbol)
  1264. {
  1265. void *pSymbol = dlsym((void *) hModule, pszSymbol);
  1266. if (pSymbol == NULL) {
  1267. ErrSetErrorCode(ERR_LOADMODULESYMBOL, pszSymbol);
  1268. return (NULL);
  1269. }
  1270. return (pSymbol);
  1271. }
  1272. int SysEventLogV(int iLogLevel, char const *pszFormat, va_list Args)
  1273. {
  1274. openlog(APP_NAME_STR, LOG_PID, LOG_DAEMON);
  1275. char szBuffer[2048] = "";
  1276. vsnprintf(szBuffer, sizeof(szBuffer) - 1, pszFormat, Args);
  1277. syslog(LOG_DAEMON | LOG_ERR, "%s", szBuffer);
  1278. closelog();
  1279. return (0);
  1280. }
  1281. int SysEventLog(int iLogLevel, char const *pszFormat, ...)
  1282. {
  1283. va_list Args;
  1284. va_start(Args, pszFormat);
  1285. int iLogResult = SysEventLogV(iLogLevel, pszFormat, Args);
  1286. va_end(Args);
  1287. return (0);
  1288. }
  1289. int SysLogMessage(int iLogLevel, char const *pszFormat, ...)
  1290. {
  1291. extern bool bServerDebug;
  1292. pthread_mutex_lock(&LogMutex);
  1293. va_list Args;
  1294. va_start(Args, pszFormat);
  1295. if (bServerDebug) {
  1296. ///////////////////////////////////////////////////////////////////////////////
  1297. //  Debug implementation
  1298. ///////////////////////////////////////////////////////////////////////////////
  1299. vprintf(pszFormat, Args);
  1300. } else {
  1301. switch (iLogLevel) {
  1302. case (LOG_LEV_WARNING):
  1303. case (LOG_LEV_ERROR):
  1304. SysEventLogV(iLogLevel, pszFormat, Args);
  1305. break;
  1306. }
  1307. }
  1308. va_end(Args);
  1309. pthread_mutex_unlock(&LogMutex);
  1310. return (0);
  1311. }
  1312. void SysSleep(int iTimeout)
  1313. {
  1314. SysMsSleep(iTimeout * 1000);
  1315. }
  1316. static int SysSetupWait(WaitData * pWD)
  1317. {
  1318. if (pthread_mutex_init(&pWD->Mtx, NULL) != 0) {
  1319. ErrSetErrorCode(ERR_MUTEXINIT);
  1320. return (ERR_MUTEXINIT);
  1321. }
  1322. if (pthread_cond_init(&pWD->WaitCond, NULL) != 0) {
  1323. pthread_mutex_destroy(&pWD->Mtx);
  1324. ErrSetErrorCode(ERR_CONDINIT);
  1325. return (ERR_CONDINIT);
  1326. }
  1327. return (0);
  1328. }
  1329. static int SysWait(WaitData * pWD, int iMsTimeout)
  1330. {
  1331. struct timespec TV;
  1332. struct timeval TmNow;
  1333. int iErrorCode;
  1334. gettimeofday(&TmNow, NULL);
  1335. TmNow.tv_sec += iMsTimeout / 1000;
  1336. TmNow.tv_usec += (iMsTimeout % 1000) * 1000;
  1337. TmNow.tv_sec += TmNow.tv_usec / 1000000;
  1338. TmNow.tv_usec %= 1000000;
  1339. TV.tv_sec = TmNow.tv_sec;
  1340. TV.tv_nsec = TmNow.tv_usec * 1000;
  1341. pthread_mutex_lock(&pWD->Mtx);
  1342. pthread_cleanup_push((void (*)(void *)) pthread_mutex_unlock, &pWD->Mtx);
  1343. iErrorCode = pthread_cond_timedwait(&pWD->WaitCond, &pWD->Mtx, &TV);
  1344. pthread_cleanup_pop(1);
  1345. if (iErrorCode == ETIMEDOUT) {
  1346. ErrSetErrorCode(ERR_TIMEOUT);
  1347. return (ERR_TIMEOUT);
  1348. }
  1349. return (0);
  1350. }
  1351. static void SysCleanupWait(WaitData * pWD)
  1352. {
  1353. pthread_mutex_destroy(&pWD->Mtx);
  1354. pthread_cond_destroy(&pWD->WaitCond);
  1355. }
  1356. void SysMsSleep(int iMsTimeout)
  1357. {
  1358. WaitData WD;
  1359. if (SysSetupWait(&WD) == 0) {
  1360. SysWait(&WD, iMsTimeout);
  1361. SysCleanupWait(&WD);
  1362. }
  1363. }
  1364. SYS_INT64 SysMsTime(void)
  1365. {
  1366. struct timeval tv;
  1367. if (gettimeofday(&tv, NULL) != 0)
  1368. return (0);
  1369. return (1000 * (SYS_INT64) tv.tv_sec + (SYS_INT64) tv.tv_usec / 1000);
  1370. }
  1371. int SysExistFile(const char *pszFilePath)
  1372. {
  1373. struct stat FS;
  1374. if (stat(pszFilePath, &FS) != 0)
  1375. return (0);
  1376. return ((S_ISDIR(FS.st_mode)) ? 0 : 1);
  1377. }
  1378. int SysExistDir(const char *pszDirPath)
  1379. {
  1380. struct stat FS;
  1381. if (stat(pszDirPath, &FS) != 0)
  1382. return (0);
  1383. return ((S_ISDIR(FS.st_mode)) ? 1 : 0);
  1384. }
  1385. SYS_HANDLE SysFirstFile(const char *pszPath, char *pszFileName)
  1386. {
  1387. DIR *pDIR = opendir(pszPath);
  1388. if (pDIR == NULL) {
  1389. ErrSetErrorCode(ERR_OPENDIR);
  1390. return (SYS_INVALID_HANDLE);
  1391. }
  1392. FilledDirent FDE;
  1393. struct dirent *pDirEntry = NULL;
  1394. #if (_POSIX_C_SOURCE - 0 >= 199506L) || defined(_POSIX_PTHREAD_SEMANTICS)
  1395. readdir_r(pDIR, &FDE.DE, &pDirEntry);
  1396. #else // #if (_POSIX_C_SOURCE - 0 >= 199506L) || ...
  1397. pDirEntry = readdir_r(pDIR, &FDE.DE);
  1398. #endif // #if (_POSIX_C_SOURCE - 0 >= 199506L) || ...
  1399. if (pDirEntry == NULL) {
  1400. closedir(pDIR);
  1401. return (SYS_INVALID_HANDLE);
  1402. }
  1403. FileFindData *pFFD = (FileFindData *) SysAlloc(sizeof(FileFindData));
  1404. if (pFFD == NULL) {
  1405. closedir(pDIR);
  1406. return (SYS_INVALID_HANDLE);
  1407. }
  1408. strcpy(pFFD->szPath, pszPath);
  1409. AppendSlash(pFFD->szPath);
  1410. pFFD->pDIR = pDIR;
  1411. pFFD->FDE = FDE;
  1412. strcpy(pszFileName, pFFD->FDE.DE.d_name);
  1413. char szFilePath[SYS_MAX_PATH] = "";
  1414. snprintf(szFilePath, sizeof(szFilePath) - 1, "%s%s", pFFD->szPath, pFFD->FDE.DE.d_name);
  1415. if (stat(szFilePath, &pFFD->FS) != 0) {
  1416. SysFree(pFFD);
  1417. closedir(pDIR);
  1418. ErrSetErrorCode(ERR_STAT);
  1419. return (SYS_INVALID_HANDLE);
  1420. }
  1421. return ((SYS_HANDLE) pFFD);
  1422. }
  1423. int SysIsDirectory(SYS_HANDLE hFind)
  1424. {
  1425. FileFindData *pFFD = (FileFindData *) hFind;
  1426. return ((S_ISDIR(pFFD->FS.st_mode)) ? 1 : 0);
  1427. }
  1428. unsigned long SysGetSize(SYS_HANDLE hFind)
  1429. {
  1430. FileFindData *pFFD = (FileFindData *) hFind;
  1431. return ((unsigned long) pFFD->FS.st_size);
  1432. }
  1433. int SysNextFile(SYS_HANDLE hFind, char *pszFileName)
  1434. {
  1435. FileFindData *pFFD = (FileFindData *) hFind;
  1436. struct dirent *pDirEntry = NULL;
  1437. #if (_POSIX_C_SOURCE - 0 >= 199506L) || defined(_POSIX_PTHREAD_SEMANTICS)
  1438. readdir_r(pFFD->pDIR, &pFFD->FDE.DE, &pDirEntry);
  1439. #else // #if (_POSIX_C_SOURCE - 0 >= 199506L) || ...
  1440. pDirEntry = readdir_r(pFFD->pDIR, &pFFD->FDE.DE);
  1441. #endif // #if (_POSIX_C_SOURCE - 0 >= 199506L) || ...
  1442. if (pDirEntry == NULL)
  1443. return (0);
  1444. strcpy(pszFileName, pFFD->FDE.DE.d_name);
  1445. char szFilePath[SYS_MAX_PATH] = "";
  1446. snprintf(szFilePath, sizeof(szFilePath) - 1, "%s%s", pFFD->szPath, pFFD->FDE.DE.d_name);
  1447. if (stat(szFilePath, &pFFD->FS) != 0) {
  1448. ErrSetErrorCode(ERR_STAT);
  1449. return (0);
  1450. }
  1451. return (1);
  1452. }
  1453. void SysFindClose(SYS_HANDLE hFind)
  1454. {
  1455. FileFindData *pFFD = (FileFindData *) hFind;
  1456. closedir(pFFD->pDIR);
  1457. SysFree(pFFD);
  1458. }
  1459. int SysGetFileInfo(char const *pszFileName, SYS_FILE_INFO & FI)
  1460. {
  1461. struct stat stat_buffer;
  1462. if (stat(pszFileName, &stat_buffer) != 0) {
  1463. ErrSetErrorCode(ERR_STAT);
  1464. return (ERR_STAT);
  1465. }
  1466. ZeroData(FI);
  1467. FI.iFileType = (S_ISREG(stat_buffer.st_mode)) ? ftNormal :
  1468. ((S_ISDIR(stat_buffer.st_mode)) ? ftDirectory :
  1469.  ((S_ISLNK(stat_buffer.st_mode)) ? ftLink : ftOther));
  1470. FI.ulSize = (unsigned long) stat_buffer.st_size;
  1471. FI.tMod = stat_buffer.st_mtime;
  1472. return (0);
  1473. }
  1474. int SysSetFileModTime(char const *pszFileName, time_t tMod)
  1475. {
  1476. struct utimbuf TMB;
  1477. TMB.actime = tMod;
  1478. TMB.modtime = tMod;
  1479. if (utime(pszFileName, &TMB) != 0) {
  1480. ErrSetErrorCode(ERR_SET_FILE_TIME);
  1481. return (ERR_SET_FILE_TIME);
  1482. }
  1483. return (0);
  1484. }
  1485. char *SysStrDup(const char *pszString)
  1486. {
  1487. int iStrLength = strlen(pszString);
  1488. char *pszBuffer = (char *) SysAlloc(iStrLength + 1);
  1489. if (pszBuffer != NULL)
  1490. strcpy(pszBuffer, pszString);
  1491. return (pszBuffer);
  1492. }
  1493. char *SysGetEnv(const char *pszVarName)
  1494. {
  1495. const char *pszValue = getenv(pszVarName);
  1496. return ((pszValue != NULL) ? SysStrDup(pszValue) : NULL);
  1497. }
  1498. char *SysGetTmpFile(char *pszFileName)
  1499. {
  1500. static unsigned long ulFileSeqNr = 0;
  1501. unsigned long ulThreadID = SysGetCurrentThreadId();
  1502. sprintf(pszFileName, "/tmp/msrv%lx.%lx.tmp", ulThreadID, ulFileSeqNr++);
  1503. return (pszFileName);
  1504. }
  1505. int SysRemove(const char *pszFileName)
  1506. {
  1507. if (unlink(pszFileName) != 0) {
  1508. ErrSetErrorCode(ERR_FILE_DELETE);
  1509. return (ERR_FILE_DELETE);
  1510. }
  1511. return (0);
  1512. }
  1513. int SysMakeDir(const char *pszPath)
  1514. {
  1515. if (mkdir(pszPath, 0700) != 0) {
  1516. ErrSetErrorCode(ERR_DIR_CREATE);
  1517. return (ERR_DIR_CREATE);
  1518. }
  1519. return (0);
  1520. }
  1521. int SysRemoveDir(const char *pszPath)
  1522. {
  1523. if (rmdir(pszPath) != 0) {
  1524. ErrSetErrorCode(ERR_DIR_DELETE);
  1525. return (ERR_DIR_DELETE);
  1526. }
  1527. return (0);
  1528. }
  1529. int SysMoveFile(char const *pszOldName, char const *pszNewName)
  1530. {
  1531. if (rename(pszOldName, pszNewName) != 0) {
  1532. ErrSetErrorCode(ERR_FILE_MOVE);
  1533. return (ERR_FILE_MOVE);
  1534. }
  1535. return (0);
  1536. }
  1537. int SysVSNPrintf(char *pszBuffer, int iSize, char const *pszFormat, va_list Args)
  1538. {
  1539. int iPrintResult = vsnprintf(pszBuffer, iSize, pszFormat, Args);
  1540. return ((iPrintResult < iSize) ? iPrintResult : -1);
  1541. }
  1542. int SysFileSync(FILE * pFile)
  1543. {
  1544. if (fflush(pFile) || fsync(fileno(pFile))) {
  1545. ErrSetErrorCode(ERR_FILE_WRITE);
  1546. return (ERR_FILE_WRITE);
  1547. }
  1548. return (0);
  1549. }
  1550. char *SysStrTok(char *pszData, char const *pszDelim, char **ppszSavePtr)
  1551. {
  1552. return (strtok_r(pszData, pszDelim, ppszSavePtr));
  1553. }
  1554. char *SysCTime(time_t * pTimer, char *pszBuffer, int iBufferSize)
  1555. {
  1556. #if (_POSIX_C_SOURCE - 0 >= 199506L) || defined(_POSIX_PTHREAD_SEMANTICS)
  1557. return (ctime_r(pTimer, pszBuffer));
  1558. #else // #if (_POSIX_C_SOURCE - 0 >= 199506L) ||
  1559. return (ctime_r(pTimer, pszBuffer, iBufferSize));
  1560. #endif // #if (_POSIX_C_SOURCE - 0 >= 199506L) ||
  1561. }
  1562. struct tm *SysLocalTime(time_t * pTimer, struct tm *pTStruct)
  1563. {
  1564. return (localtime_r(pTimer, pTStruct));
  1565. }
  1566. struct tm *SysGMTime(time_t * pTimer, struct tm *pTStruct)
  1567. {
  1568. return (gmtime_r(pTimer, pTStruct));
  1569. }
  1570. char *SysAscTime(struct tm *pTStruct, char *pszBuffer, int iBufferSize)
  1571. {
  1572. #if (_POSIX_C_SOURCE - 0 >= 199506L) || defined(_POSIX_PTHREAD_SEMANTICS)
  1573. return (asctime_r(pTStruct, pszBuffer));
  1574. #else // #if (_POSIX_C_SOURCE - 0 >= 199506L) ||
  1575. return (asctime_r(pTStruct, pszBuffer, iBufferSize));
  1576. #endif // #if (_POSIX_C_SOURCE - 0 >= 199506L) ||
  1577. }
  1578. long SysGetTimeZone(void)
  1579. {
  1580. return ((long) timezone);
  1581. }
  1582. long SysGetDayLight(void)
  1583. {
  1584. time_t tCurr = time(NULL);
  1585. struct tm tmCurr;
  1586. localtime_r(&tCurr, &tmCurr);
  1587. return ((long) ((tmCurr.tm_isdst <= 0) ? 0 : 3600));
  1588. }
  1589. int SysGetDiskSpace(char const *pszPath, SYS_INT64 * pTotal, SYS_INT64 * pFree)
  1590. {
  1591. struct statvfs SFS;
  1592. if (statvfs(pszPath, &SFS) != 0) {
  1593. ErrSetErrorCode(ERR_GET_DISK_SPACE_INFO);
  1594. return (ERR_GET_DISK_SPACE_INFO);
  1595. }
  1596. *pTotal = (SYS_INT64) SFS.f_bsize * (SYS_INT64) SFS.f_blocks;
  1597. *pFree = (SYS_INT64) SFS.f_bsize * (SYS_INT64) SFS.f_bavail;
  1598. return (0);
  1599. }
  1600. int SysMemoryInfo(SYS_INT64 * pRamTotal, SYS_INT64 * pRamFree,
  1601.   SYS_INT64 * pVirtTotal, SYS_INT64 * pVirtFree)
  1602. {
  1603. SYS_INT64 SwapTotal;
  1604. SYS_INT64 SwapFree;
  1605. if (SysGetSwapInfo(&SwapTotal, &SwapFree) < 0) {
  1606. ErrSetErrorCode(ERR_GET_MEMORY_INFO);
  1607. return (ERR_GET_MEMORY_INFO);
  1608. }
  1609. SYS_INT64 PageSize = (SYS_INT64) sysconf(_SC_PAGESIZE);
  1610. *pRamTotal = (SYS_INT64) sysconf(_SC_PHYS_PAGES) * PageSize;
  1611. *pRamFree = (SYS_INT64) sysconf(_SC_AVPHYS_PAGES) * PageSize;
  1612. *pVirtTotal = SwapTotal + *pRamTotal;
  1613. *pVirtFree = SwapFree + *pRamFree;
  1614. return (0);
  1615. }
  1616. static int SysGetSwapInfo(SYS_INT64 * pSwapTotal, SYS_INT64 * pSwapFree)
  1617. {
  1618. *pSwapTotal = *pSwapFree = 0;
  1619. int iNumSwaps = swapctl(SC_GETNSWP, 0);
  1620. if (iNumSwaps == -1)
  1621. return (-1);
  1622. if (iNumSwaps == 0)
  1623. return (0);
  1624. swaptbl_t *pSwTab = (swaptbl_t *) malloc(iNumSwaps * sizeof(swapent_t) +
  1625.  sizeof(struct swaptable));
  1626. if (pSwTab == (void *) 0)
  1627. return (-1);
  1628. memset(pSwTab, 0, iNumSwaps * sizeof(swapent_t) + sizeof(struct swaptable));
  1629. char *pszNameTab = (char *) malloc(iNumSwaps * MAX_SWAP_NAME_SIZE);
  1630. if (pszNameTab == (void *) 0) {
  1631. free(pSwTab);
  1632. return (-1);
  1633. }
  1634. memset(pszNameTab, 0, iNumSwaps * MAX_SWAP_NAME_SIZE);
  1635. int ii;
  1636. for (ii = 0; ii < iNumSwaps; ii++)
  1637. pSwTab->swt_ent[ii].ste_path = pszNameTab + (ii * MAX_SWAP_NAME_SIZE);
  1638. pSwTab->swt_n = iNumSwaps;
  1639. if ((iNumSwaps = swapctl(SC_LIST, pSwTab)) < 0) {
  1640. free(pszNameTab);
  1641. free(pSwTab);
  1642. return (-1);
  1643. }
  1644. SYS_INT64 PageSize = (SYS_INT64) sysconf(_SC_PAGESIZE);
  1645. for (ii = 0; ii < iNumSwaps; ii++) {
  1646. *pSwapTotal += (SYS_INT64) pSwTab->swt_ent[ii].ste_pages * PageSize;
  1647. *pSwapFree += (SYS_INT64) pSwTab->swt_ent[ii].ste_free * PageSize;
  1648. }
  1649. free(pszNameTab);
  1650. free(pSwTab);
  1651. return (0);
  1652. }
  1653. static unsigned int SysStkCall(unsigned int (*pProc) (void *), void *pData)
  1654. {
  1655. srand(getpid() * (unsigned int) time(NULL) * uSRandBase);
  1656. unsigned int uResult;
  1657. unsigned int uStkDisp =
  1658. (unsigned int) (rand() % MAX_STACK_SHIFT) & ~(STACK_ALIGN_BYTES - 1);
  1659. void *pStkSpace = alloca(uStkDisp);
  1660. uResult = pProc(pData);
  1661. return (uResult);
  1662. }