NCBI C++ ToolKit
threadsafe.c
Go to the documentation of this file.

Go to the SVN repository for this file.

Go to the SVN repository for this file.

Go to the SVN repository for this file.

Go to the SVN repository for this file.

1 /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Brian Bruns
3  * Copyright (C) 2005-2015 Frediano Ziglio
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 
21 #include <config.h>
22 
23 #include <stdarg.h>
24 #include <stdio.h>
25 
26 #if HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif /* HAVE_UNISTD_H */
29 
30 #include <freetds/time.h>
31 
32 #if defined(HAVE_GETUID) && defined(HAVE_GETPWUID)
33 #include <pwd.h>
34 #endif
35 
36 #if HAVE_STDLIB_H
37 #include <stdlib.h>
38 #endif /* HAVE_STDLIB_H */
39 
40 #if HAVE_STRING_H
41 #include <string.h>
42 #endif /* HAVE_STRING_H */
43 
44 #if HAVE_NETDB_H
45 #include <netdb.h>
46 #endif /* HAVE_NETDB_H */
47 
48 #if HAVE_ERRNO_H
49 #include <errno.h>
50 #endif /* HAVE_ERRNO_H */
51 
52 #if HAVE_SYS_SOCKET_H
53 #include <sys/socket.h>
54 #endif /* HAVE_SYS_SOCKET_H */
55 
56 #if HAVE_NETINET_IN_H
57 #include <netinet/in.h>
58 #endif /* HAVE_NETINET_IN_H */
59 
60 #if HAVE_ARPA_INET_H
61 #include <arpa/inet.h>
62 #endif /* HAVE_ARPA_INET_H */
63 
64 #if HAVE_ROKEN_H
65 #include <roken.h>
66 #endif /* HAVE_ROKEN_H */
67 
68 #if defined(_WIN32) || defined(_WIN64)
69 #include <winsock2.h>
70 #include <shlobj.h>
71 #endif
72 
73 #include <freetds/tds.h>
74 #include <freetds/thread.h>
75 #include "replacements.h"
76 
77 struct tm *
78 tds_localtime_r(const time_t *timep, struct tm *result)
79 {
80  struct tm *tm;
81 
82 #if defined(_REENTRANT) && !defined(_WIN32)
83 #if HAVE_FUNC_LOCALTIME_R_TM
84  tm = localtime_r(timep, result);
85 #else
86  tm = NULL;
87  if (!localtime_r(timep, result))
88  tm = result;
89 #endif /* HAVE_FUNC_LOCALTIME_R_TM */
90 #else
91  tm = localtime(timep);
92  if (tm) {
93  memcpy(result, tm, sizeof(*result));
94  tm = result;
95  }
96 #endif
97  return tm;
98 }
99 
100 char *
101 tds_timestamp_str(char *str, int maxlen)
102 {
103 #if !defined(_WIN32) && !defined(_WIN64)
104  struct tm *tm;
105  struct tm res;
106  time_t t;
107 
108 #if HAVE_GETTIMEOFDAY
109  struct timeval tv;
110  char usecs[10];
111 
112  gettimeofday(&tv, NULL);
113  t = tv.tv_sec;
114 #else
115  /*
116  * XXX Need to get a better time resolution for
117  * systems that don't have gettimeofday().
118  */
119  time(&t);
120 #endif
121 
122  tm = tds_localtime_r(&t, &res);
123 
124 /** strftime(str, maxlen - 6, "%Y-%m-%d %H:%M:%S", tm); **/
125  strftime(str, maxlen - 6, "%H:%M:%S", tm);
126 
127 #if HAVE_GETTIMEOFDAY
128  sprintf(usecs, ".%06lu", (long) tv.tv_usec);
129  strcat(str, usecs);
130 #endif
131 
132 #else /* _WIN32 */
133  SYSTEMTIME st;
134 
135  GetLocalTime(&st);
136  _snprintf(str, maxlen - 1, "%02u:%02u:%02u.%03u", st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
137  str[maxlen - 1] = 0;
138 #endif
139 
140  return str;
141 }
142 
143 /*
144  * If reentrant code was not requested, we don't care reentrancy, so
145  * just assume the standard BSD netdb interface is reentrant and use it.
146  */
147 #ifndef _REENTRANT
148 # undef NETDB_REENTRANT
149 # define NETDB_REENTRANT 1
150 #endif /* _REENTRANT */
151 
152 #if !defined(HAVE_GETADDRINFO)
153 
154 #if defined(NETDB_REENTRANT)
155 struct hostent *
156 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
157 {
158  return gethostbyname(servername);
159 }
160 
161 #elif defined(HAVE_GETIPNODEBYNAME) || defined(HAVE_GETIPNODEBYADDR)
162 /**
163  * Copy a hostent structure to an allocated buffer
164  * @return 0 on success, -1 otherwise
165  */
166 static int
167 tds_copy_hostent(struct hostent *he, struct hostent *result, char *buffer, int buflen)
168 {
169 #define CHECK_BUF(len) \
170  if (p + sizeof(struct hostent) - buffer > buflen) return -1;
171 #define ALIGN_P do { p += TDS_ALIGN_SIZE - 1; p -= (p-buffer) % TDS_ALIGN_SIZE; } while(0)
172 
173  int n, i;
174  char *p = buffer;
175  struct hostent *he2;
176 
177  /* copy structure */
178  he2 = result;
179  memcpy(he2, he, sizeof(struct hostent));
180 
181  if (he->h_addr_list) {
182  int len;
183  char **addresses;
184 
185  /* count addresses */
186  for (n = 0; he->h_addr_list[n]; ++n)
187  continue;
188 
189  /* copy addresses */
190  addresses = (char **) p;
191  he2->h_addr_list = (char **) p;
192  len = sizeof(char *) * (n + 1);
193  CHECK_BUF(len);
194  p += len;
195  ALIGN_P;
196  for (i = 0; i < n; ++i) {
197  addresses[i] = p;
198 
199  CHECK_BUF(he->h_length);
200  memcpy(p, he->h_addr_list[i], he->h_length);
201  p += he->h_length;
202  ALIGN_P;
203  }
204  addresses[n] = NULL;
205  }
206 
207  /* copy name */
208  if (he->h_name) {
209  n = strlen(he->h_name) + 1;
210  he2->h_name = p;
211  CHECK_BUF(n);
212  memcpy(p, he->h_name, n);
213  p += n;
214  ALIGN_P;
215  }
216 
217  if (he->h_aliases) {
218  int len;
219  char **aliases;
220 
221  /* count aliases */
222  for (n = 0; he->h_aliases[n]; ++n)
223  continue;
224 
225  /* copy aliases */
226  aliases = (char **) p;
227  he2->h_aliases = (char **) p;
228  len = sizeof(char *) * (n + 1);
229  CHECK_BUF(len);
230  p += len;
231  for (i = 0; i < n; ++i) {
232  len = strlen(he->h_aliases[i]) + 1;
233  aliases[i] = p;
234 
235  CHECK_BUF(len);
236  memcpy(p, he->h_aliases[i], len);
237  p += len;
238  }
239  aliases[n] = NULL;
240  }
241  return 0;
242 }
243 
244 struct hostent *
245 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
246 {
247  struct hostent *he = getipnodebyname(servername, AF_INET, 0, h_errnop);
248 
249  if (!he)
250  return NULL;
251  if (tds_copy_hostent(he, result, buffer, buflen)) {
252  errno = ENOMEM;
253  if (h_errnop)
254  *h_errnop = NETDB_INTERNAL;
255  freehostent(he);
256  return NULL;
257  }
258  freehostent(he);
259  return result;
260 }
261 
262 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_6)
263 struct hostent *
264 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
265 {
266  if (gethostbyname_r(servername, result, buffer, buflen, &result, h_errnop))
267  return NULL;
268  return result;
269 }
270 
271 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5)
272 struct hostent *
273 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
274 {
275  result = gethostbyname_r(servername, result, buffer, buflen, h_errnop);
276  return result;
277 }
278 
279 #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_3)
280 struct hostent *
281 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
282 {
283  struct hostent_data *data = (struct hostent_data *) buffer;
284 
285  memset(buffer, 0, buflen);
286  if (gethostbyname_r(servername, result, data)) {
287  *h_errnop = 0;
288  result = NULL;
289  }
290  return result;
291 }
292 
293 #elif defined(TDS_NO_THREADSAFE)
294 struct hostent *
295 tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
296 {
297  return gethostbyname(servername);
298 }
299 
300 #else
301 #error gethostbyname_r style unknown
302 #endif
303 
304 #endif
305 
306 
307 #if 0
308 #undef HAVE_GETADDRINFO
309 #undef NETDB_REENTRANT
310 #undef HAVE_FUNC_GETSERVBYNAME_R_6
311 #undef HAVE_FUNC_GETSERVBYNAME_R_5
312 #undef HAVE_FUNC_GETSERVBYNAME_R_4
313 #undef TDS_NO_THREADSAFE
314 
315 # if 0
316 # define HAVE_FUNC_GETSERVBYNAME_R_6 1
317 int test_getservbyname_r(const char *name, const char *proto,
318  struct servent *result_buf, char *buffer,
319  size_t buflen, struct servent **result);
320 # define getservbyname_r test_getservbyname_r
321 # elif 0
322 # define HAVE_FUNC_GETSERVBYNAME_R_5 1
323 struct servent *
324 test_getservbyname_r(const char *name, const char *proto,
325  struct servent *result_buf, char *buffer,
326  size_t buflen);
327 # define getservbyname_r test_getservbyname_r
328 # else
329 # define HAVE_FUNC_GETSERVBYNAME_R_4 1
330 struct servent_data { int dummy; };
331 int
332 test_getservbyname_r(const char *name, const char *proto,
333  struct servent *result_buf,
334  struct servent_data *data);
335 # define getservbyname_r test_getservbyname_r
336 # endif
337 #endif
338 
339 /**
340  * Return service port given the name
341  */
342 int
343 tds_getservice(const char *name)
344 {
345 #if defined(HAVE_GETADDRINFO)
346  /* new OSes should implement this in a proper way */
347  struct addrinfo hints, *res;
348  int result;
349 
350  memset(&hints, 0, sizeof(hints));
351  hints.ai_family = AF_INET;
352  hints.ai_socktype = SOCK_STREAM;
353  hints.ai_flags = AI_PASSIVE;
354 #ifdef AI_CANONNAME
355  hints.ai_flags |= AI_CANONNAME;
356 #endif
357  res = NULL;
358  if (getaddrinfo(NULL, name, &hints, &res))
359  return 0;
360  if (res->ai_family != AF_INET || !res->ai_addr) {
361  freeaddrinfo(res);
362  return 0;
363  }
364  result = ntohs(((struct sockaddr_in *) res->ai_addr)->sin_port);
365  freeaddrinfo(res);
366  return result;
367 
368 #elif defined(NETDB_REENTRANT)
369  /* HP-UX/Windows */
370  struct servent *result = getservbyname(name, "tcp");
371  return result ? ntohs(result->s_port) : 0;
372 
373 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_6)
374  /* Linux variant */
375  struct servent *result = NULL;
376  struct servent result_buf;
377  char buffer[4096];
378 
379  if (!getservbyname_r(name, "tcp", &result_buf, buffer, sizeof(buffer), &result))
380  return ntohs(result->s_port);
381  return 0;
382 
383 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_5)
384  /* Solaris variant */
385  struct servent result;
386  char buffer[4096];
387 
388  if (getservbyname_r(name, "tcp", &result, buffer, sizeof(buffer)))
389  return ntohs(result.s_port);
390  return 0;
391 
392 #elif defined(HAVE_FUNC_GETSERVBYNAME_R_4)
393  /* AIX/BSD variant */
394  struct servent result;
395  struct servent_data data;
396 
397  if (!getservbyname_r(name, "tcp", &result, &data))
398  return ntohs(result.s_port);
399  return 0;
400 
401 #elif defined(TDS_NO_THREADSAFE)
402  struct servent *result = getservbyname(name, "tcp");
403  return result ? ntohs(result->s_port) : 0;
404 #else
405 #error getservbyname_r style unknown
406 #endif
407 }
408 
409 /**
410  * Get user home directory
411  * @return home directory or NULL if error. Should be freed with free
412  */
413 char *
415 {
416 #ifndef _WIN32
417 /* if is available getpwuid_r use it */
418 #if defined(HAVE_GETUID) && defined(HAVE_GETPWUID_R)
419  struct passwd *pw, bpw;
420  char buf[1024];
421 
422 # if defined(HAVE_FUNC_GETPWUID_R_5)
423  /* getpwuid_r can return 0 if uid is not found so check pw */
424  pw = NULL;
425  if (getpwuid_r(getuid(), &bpw, buf, sizeof(buf), &pw) || !pw)
426  return NULL;
427 
428 # elif defined(HAVE_FUNC_GETPWUID_R_4_PW)
429  if (!(pw = getpwuid_r(getuid(), &bpw, buf, sizeof(buf))))
430  return NULL;
431 # else /* !HAVE_FUNC_GETPWUID_R_4_PW */
432  if (getpwuid_r(getuid(), &bpw, buf, sizeof(buf)))
433  return NULL;
434  pw = &bpw;
435 # endif
436 
437  return strdup(pw->pw_dir);
438 
439 /* if getpwuid is available use it for no reentrant (getpwuid is not reentrant) */
440 #elif defined(HAVE_GETUID) && defined(HAVE_GETPWUID) && !defined(_REENTRANT)
441  struct passwd *pw;
442 
443  pw = getpwuid(getuid());
444  if (!pw)
445  return NULL;
446  return strdup(pw->pw_dir);
447 #else
448  char *home;
449 
450  home = getenv("HOME");
451  if (!home || !home[0])
452  return NULL;
453  return strdup(home);
454 #endif
455 #else /* _WIN32 */
456  /*
457  * For win32 we return application data cause we use "HOME"
458  * only to store configuration files
459  */
460  LPITEMIDLIST pidl;
461  /*
462  * SHGetPathFromIDListA() tries to count the length of "path",
463  * so we have to make sure that it has only zeros; otherwise,
464  * invalid memory access is inevitable.
465  */
466  char path[MAX_PATH] = "";
467  HRESULT hr;
468  LPMALLOC pMalloc = NULL;
469  char * res = NULL;
470 
471  hr = SHGetMalloc(&pMalloc);
472  if (!FAILED(hr)) {
473  hr = SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl);
474  if (!FAILED(hr)) {
475  if (SHGetPathFromIDListA(pidl, path))
476  res = strdup(path);
477  (*pMalloc->lpVtbl->Free)(pMalloc, pidl);
478  }
479  (*pMalloc->lpVtbl->Release)(pMalloc);
480  }
481  return res;
482 #endif
483 }
484 
static CBioSource dummy
#define NULL
Definition: ncbistd.hpp:225
char * buf
int i
yy_size_t n
int len
#define strdup
Definition: ncbi_ansi_ext.h:70
EIPRangeType t
Definition: ncbi_localip.c:101
const double FAILED
Definition: njn_root.hpp:55
static pcre_uint8 * buffer
Definition: pcretest.c:1051
#define getaddrinfo(n, s, h, r)
Definition: replacements.h:99
#define addrinfo
Definition: replacements.h:98
#define freeaddrinfo(a)
Definition: replacements.h:101
#define strcat(s, k)
static const char * str(char *buf, int n)
Definition: stats.c:84
Main include file for libtds.
struct tm * tds_localtime_r(const time_t *timep, struct tm *result)
Definition: threadsafe.c:78
int tds_getservice(const char *name)
Return service port given the name.
Definition: threadsafe.c:343
char * tds_get_homedir(void)
Get user home directory.
Definition: threadsafe.c:414
char * tds_timestamp_str(char *str, int maxlen)
Definition: threadsafe.c:101
struct hostent * tds_gethostbyname_r(const char *servername, struct hostent *result, char *buffer, int buflen, int *h_errnop)
Definition: threadsafe.c:156
else result
Definition: token2.c:20
Modified on Tue Apr 09 07:56:43 2024 by modify_doxy.py rev. 669887
Modified on Wed Apr 10 07:32:07 2024 by modify_doxy.py rev. 669887
Modified on Thu Apr 11 15:04:20 2024 by modify_doxy.py rev. 669887
Modified on Fri Apr 12 17:16:19 2024 by modify_doxy.py rev. 669887