threadsafe.c
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:10k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: threadsafe.c,v $
  4.  * PRODUCTION Revision 1000.2  2004/04/01 21:01:21  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [CORE_002] Dev-tree R1.4
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
  10.  * Copyright (C) 1998-2002  Brian Bruns
  11.  *
  12.  * This library is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU Library General Public
  14.  * License as published by the Free Software Foundation; either
  15.  * version 2 of the License, or (at your option) any later version.
  16.  *
  17.  * This library is distributed in the hope that it will be useful,
  18.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  20.  * Library General Public License for more details.
  21.  *
  22.  * You should have received a copy of the GNU Library General Public
  23.  * License along with this library; if not, write to the
  24.  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  25.  * Boston, MA 02111-1307, USA.
  26.  */
  27. #include <tds_config.h>
  28. #ifndef WIN32
  29. #include <netdb.h>
  30. #include <sys/types.h>
  31. #include <netinet/in.h>
  32. #include <arpa/inet.h>
  33. #endif
  34. #include "tds.h"
  35. #include "tdsutil.h"
  36. #ifdef DMALLOC
  37. #include <dmalloc.h>
  38. #endif
  39. static char  software_version[]   = "$Id: threadsafe.c,v 1000.2 2004/04/01 21:01:21 gouriano Exp $";
  40. static void *no_unused_var_warn[] = {software_version,
  41.                                      no_unused_var_warn};
  42. char *
  43. tds_timestamp_str(char *str, int maxlen)
  44. {
  45. struct tm  *tm;
  46. time_t      t;
  47. #ifdef __FreeBSD__
  48. struct timeval  tv;
  49. char usecs[10];
  50. #endif
  51. #ifdef _REENTRANT
  52. struct tm res;
  53. #endif
  54. #ifdef __FreeBSD__
  55. gettimeofday(&tv, NULL);
  56. t = tv.tv_sec;
  57. #else
  58. /*
  59. * XXX Need to get a better time resolution for
  60. * non-FreeBSD systems.
  61. */
  62. time(&t);
  63. #endif
  64. #ifdef _REENTRANT
  65. tm = localtime_r(&t, &res);
  66. #else
  67. tm = localtime(&t);
  68. #endif
  69. strftime(str, maxlen - 6, "%Y-%m-%d %H:%M:%S", tm);
  70. #ifdef __FreeBSD__
  71.     sprintf(usecs, ".%06lu", tv.tv_usec);
  72. strcat(str, usecs);
  73. #endif
  74. return str;
  75. }
  76. #if (defined(HAVE_GETADDRINFO) || defined(HAVE_GETNAMEINFO))  &&  defined(_REENTRANT)
  77. static
  78. int s_make_hostent(struct hostent* he, char* buf, int len, const struct addrinfo* ai)
  79. {
  80. static int ptr_size = sizeof(char*);
  81. int pos = 0, namelen, addrnum = 0, maxaddrs;
  82. const struct addrinfo* it;
  83. memset(he, 0, sizeof(*he));
  84. namelen = strlen(ai->ai_canonname);
  85. if (pos + namelen >= len) {
  86. return NO_RECOVERY;
  87. }
  88. if (he->h_name != ai->ai_canonname) {
  89. /* already present in dummy structure passed by tds_ghba_r */
  90. he->h_name = strcpy(buf + pos, ai->ai_canonname);
  91. }
  92. pos += namelen;
  93. pos += ptr_size - ((pos + (size_t)buf) % ptr_size); /* align */
  94. if (pos + ptr_size > len) {
  95. return NO_RECOVERY;
  96. }
  97. he->h_aliases = (char**)(buf + pos);
  98. he->h_aliases[0] = 0;
  99. pos += ptr_size;
  100. he->h_addrtype = ai->ai_family;
  101. he->h_length = ai->ai_addrlen;
  102. if (pos + ptr_size > len) {
  103. return NO_RECOVERY;
  104. }
  105. he->h_addr_list = (char**)(buf + pos);
  106. pos += ptr_size;
  107. maxaddrs = (len - pos) / (ptr_size + ai->ai_addrlen);
  108. if (maxaddrs == 0) {
  109. he->h_addr_list[0] = 0;
  110. return NO_RECOVERY;
  111. }
  112. pos += ptr_size * maxaddrs;
  113. for (it = ai;  it != 0  &&  addrnum < maxaddrs;  it = it->ai_next) {
  114. if (it->ai_family == ai->ai_family) {
  115. switch (ai->ai_family) {
  116. case PF_INET:
  117. memcpy(buf + pos,
  118.        &((struct sockaddr_in*)(it->ai_addr))
  119.            ->sin_addr,
  120.        it->ai_addrlen);
  121. break;
  122. case PF_INET6:
  123. memcpy(buf + pos,
  124.        &((struct sockaddr_in6*)(it->ai_addr))
  125.            ->sin6_addr,
  126.        it->ai_addrlen);
  127. break;
  128. }
  129. he->h_addr_list[addrnum] = buf + pos;
  130. pos += it->ai_addrlen;
  131. ++addrnum;
  132. }
  133. }
  134. he->h_addr_list[addrnum] = 0;
  135. return 0;
  136. }
  137. static
  138. int s_convert_ai_errno(int ai_errno)
  139. {
  140. switch (ai_errno) {
  141. case EAI_NONAME:      return HOST_NOT_FOUND;
  142. case EAI_ADDRFAMILY:  return NO_ADDRESS;
  143. case EAI_NODATA:      return NO_DATA;
  144. case EAI_FAIL:        return NO_RECOVERY;
  145. case EAI_AGAIN:       return TRY_AGAIN;
  146. default:              return TRY_AGAIN;
  147. }
  148. }
  149. #endif
  150. struct hostent   *
  151. tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
  152. {
  153. #ifndef _REENTRANT
  154.         return gethostbyname(servername);
  155. #else
  156. #if defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
  157. if (gethostbyname_r(servername, result, buffer, buflen, &result, h_errnop))
  158. return NULL;
  159. #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
  160.         gethostbyname_r(servername, result, buffer, buflen, h_errnop);
  161. #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
  162. struct hostent_data data;
  163. gethostbyname_r(servername, result, &data);
  164. #elif defined(HAVE_GETADDRINFO)
  165. struct addrinfo hints, *out = 0;
  166. int ai_errno;
  167. memset(&hints, 0, sizeof(hints));
  168. hints.ai_family = PF_INET;
  169. ai_errno = getaddrinfo(servername, 0, &hints, &out);
  170. if (ai_errno == 0  &&  out) {
  171. *h_errnop = s_make_hostent(result, buffer, buflen, out);
  172. } else {
  173. *h_errnop = s_convert_ai_errno(ai_errno);
  174. }
  175. if (out) {
  176. freeaddrinfo(out);
  177. }
  178. #elif defined(_REENTRANT)
  179. #error gethostbyname_r style unknown and getaddrinfo unavailable
  180. #endif
  181.         return result;
  182. #endif
  183. }
  184. #if defined(HAVE_GETNAMEINFO)  &&  defined(_REENTRANT)
  185. #  ifndef HAVE_SOCKLEN_T
  186. typedef int socklen_t;
  187. #  endif
  188. static
  189. socklen_t s_make_sa(const char *addr, int len, int type, void *buf, int blen)
  190. {
  191. switch (type) {
  192. case PF_INET:
  193. {
  194. struct sockaddr_in* sain = (struct sockaddr_in*)buf;
  195. if (sizeof(*sain) > blen) {
  196. return 0;
  197. }
  198. memset(sain, 0, sizeof(*sain));
  199. sain->sin_family = type;
  200. memcpy(&sain->sin_addr, addr, len);
  201. #ifdef HAVE_SIN_LEN
  202. sain->sin_len = len;
  203. #endif
  204. return sizeof(*sain);
  205. }
  206. #ifdef PF_INET6
  207. case PF_INET6:
  208. {
  209. struct sockaddr_in6* sa6 = (struct sockaddr_in6*)buf;
  210. if (sizeof(*sa6) > blen) {
  211. return 0;
  212. }
  213. memset(sa6, 0, sizeof(*sa6));
  214. sa6->sin6_family = type;
  215. memcpy(&sa6->sin6_addr, addr, len);
  216. #ifdef HAVE_SIN_LEN
  217. sa6->sin6_len = len;
  218. #endif
  219. return sizeof(*sa6);
  220. }
  221. #endif
  222. default:
  223. return 0;
  224. }
  225. }
  226. #endif
  227. struct hostent   *
  228. tds_gethostbyaddr_r(const char *addr, int len, int type, struct hostent *result, char *buffer, int buflen, int *h_errnop)
  229. {
  230. #ifndef _REENTRANT
  231.         return gethostbyaddr(addr, len, type);
  232. #else
  233. #if defined(HAVE_FUNC_GETHOSTBYADDR_R_8)
  234. if (gethostbyaddr_r(addr, len, type, result, buffer, buflen, &result, h_errnop))
  235. return NULL;
  236. #elif defined(HAVE_FUNC_GETHOSTBYADDR_R_7)
  237.         gethostbyaddr_r(addr, len, type, result, buffer, buflen, h_errnop);
  238. #elif defined(HAVE_FUNC_GETHOSTBYADDR_R_5)
  239. struct hostent_data data;
  240. gethostbyaddr_r(addr, len, type, result, &data);
  241. #elif defined(HAVE_GETNAMEINFO)
  242. struct sockaddr* sa = (struct sockaddr*)buffer;
  243. socklen_t salen;
  244. int ai_errno;
  245. salen = s_make_sa(addr, len, type, buffer, buflen);
  246. if (salen <= 0) {
  247. *h_errnop = NO_RECOVERY;
  248. return NULL;
  249. }
  250. ai_errno = getnameinfo(sa, salen, buffer + salen, buflen - salen, 0, 0, 0);
  251. if (ai_errno == 0) {
  252. struct addrinfo ai; /* much easier to construct than hostent */
  253. ai.ai_family  = type;
  254. ai.ai_addrlen  = salen;
  255. ai.ai_addr  = sa;
  256. ai.ai_canonname = buffer + salen;
  257. ai.ai_next  = 0;
  258. *h_errnop = s_make_hostent(result, buffer + salen, buflen - salen, &ai);
  259. } else {
  260. *h_errnop = s_convert_ai_errno(ai_errno);
  261. }
  262. #else
  263. #error gethostbyaddr_r style unknown and getnameinfo unavailable
  264. #endif
  265.         return result;
  266. #endif
  267. }
  268. #if defined(HAVE_GETADDRINFO)  &&  defined(_REENTRANT)
  269. static
  270. int s_make_servent(struct servent* se, char* buf, int len, const struct addrinfo* ai, const char* name, const char* proto)
  271. {
  272. static int ptr_size = sizeof(char*);
  273. int pos = 0, namelen;
  274. const struct addrinfo* it;
  275. memset(se, 0, sizeof(*se));
  276. namelen = strlen(name);
  277. if (pos + namelen >= len) {
  278. return NO_RECOVERY;
  279. }
  280. se->s_name = strcpy(buf + pos, ai->ai_canonname);
  281. pos += namelen;
  282. pos += ptr_size - ((pos + (size_t)buf) % ptr_size); /* align */
  283. if (pos + ptr_size > len) {
  284. return NO_RECOVERY;
  285. }
  286. se->s_aliases = (char**)(buf + pos);
  287. se->s_aliases[0] = 0;
  288. pos += ptr_size;
  289. switch (ai->ai_family) {
  290. case PF_INET:
  291. se->s_port = ((struct sockaddr_in*)(it->ai_addr))->sin_port;
  292. break;
  293. case PF_INET6:
  294. se->s_port = ((struct sockaddr_in6*)(it->ai_addr))->sin6_port;
  295. break;
  296. }
  297. if (proto  &&  pos + strlen(proto) < len) {
  298. se->s_proto = strcpy(buf + pos, proto);
  299. pos += strlen(proto) + 1;
  300. }
  301. return 0;
  302. }
  303. #endif
  304. struct servent *
  305. tds_getservbyname_r(const char *name, char *proto, struct servent *result, char *buffer, int buflen)
  306. {
  307. #ifndef _REENTRANT
  308.         return getservbyname(name, proto);
  309. #else
  310. #if defined(HAVE_FUNC_GETSERVBYNAME_R_6)
  311. if (getservbyname_r(name, proto, result, buffer, buflen, &result))
  312. return NULL;
  313. #elif defined(HAVE_FUNC_GETSERVBYNAME_R_5)
  314.         getservbyname_r(name, proto, result, buffer, buflen);
  315. #elif defined(HAVE_FUNC_GETSERVBYNAME_R_4)
  316. struct servent_data data;
  317. getservbyname_r(name, proto, result, &data);
  318. #elif defined(HAVE_GETADDRINFO)
  319. struct addrinfo hints, *out = 0;
  320. struct protoent* pe;
  321. int status;
  322. memset(&hints, 0, sizeof(hints));
  323. hints.ai_family = PF_INET;
  324. if (proto) {
  325. pe = getprotobyname(proto);
  326. if (pe) {
  327. /* might as well canonicalize */
  328. proto             = pe->p_name;
  329. hints.ai_protocol = pe->p_proto;
  330. }
  331. }
  332. status = getaddrinfo(0, name, &hints, &out);
  333. if (status == 0  &&  out) {
  334. status = s_make_servent(result, buffer, buflen, out, name, proto);
  335. if (status != 0) {
  336. result = 0;
  337. }
  338. } else {
  339. result = 0;
  340. }
  341. if (out) {
  342. freeaddrinfo(out);
  343. }
  344. #else
  345. #error getservbyname_r style unknown and getaddrinfo unavailable
  346. #endif
  347.         return result;
  348. #endif
  349. }
  350. char *
  351. tds_strtok_r(char *s, const char *delim, char **ptrptr)
  352. {
  353. #ifdef _REENTRANT
  354. return strtok_r(s, delim, ptrptr);
  355. #else
  356. return strtok(s, delim);
  357. #endif
  358. }