NCBI C++ ToolKit
config.c
Go to the documentation of 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, 2005 Brian Bruns
3  * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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_ERRNO_H
27 #include <errno.h>
28 #endif /* HAVE_ERRNO_H */
29 
30 #include <assert.h>
31 #include <ctype.h>
32 
33 #if HAVE_STDLIB_H
34 #include <stdlib.h>
35 #endif /* HAVE_STDLIB_H */
36 
37 #if HAVE_LIMITS_H
38 #include <limits.h>
39 #endif
40 
41 #if HAVE_STRING_H
42 #include <string.h>
43 #endif /* HAVE_STRING_H */
44 
45 #if HAVE_UNISTD_H
46 #include <unistd.h>
47 #endif /* HAVE_UNISTD_H */
48 
49 #if HAVE_NETDB_H
50 #include <netdb.h>
51 #endif /* HAVE_NETDB_H */
52 
53 #if HAVE_SYS_SOCKET_H
54 #include <sys/socket.h>
55 #endif /* HAVE_SYS_SOCKET_H */
56 
57 #if HAVE_SYS_TYPES_H
58 #include <sys/types.h>
59 #endif /* HAVE_SYS_TYPES_H */
60 
61 #if HAVE_NETINET_IN_H
62 #include <netinet/in.h>
63 #endif /* HAVE_NETINET_IN_H */
64 
65 #if HAVE_ARPA_INET_H
66 #include <arpa/inet.h>
67 #endif /* HAVE_ARPA_INET_H */
68 
69 #ifdef _WIN32
70 #include <process.h>
71 #endif
72 
73 #include <freetds/tds.h>
74 #include <freetds/configs.h>
75 #include <freetds/string.h>
76 #include "replacements.h"
77 
78 static int tds_config_login(TDSLOGIN * connection, TDSLOGIN * login);
80 static void tds_config_env_tdsver(TDSLOGIN * login);
83 static int tds_read_conf_sections(FILE * in, const char *server, TDSLOGIN * login);
84 static int tds_read_interfaces(const char *server, TDSLOGIN * login);
85 static int parse_server_name_for_port(TDSLOGIN * connection, TDSLOGIN * login);
86 static int tds_lookup_port(const char *portname);
87 static void tds_config_encryption(const char * value, TDSLOGIN * login);
88 
89 static char *interf_file = NULL;
90 
91 #define TDS_ISSPACE(c) isspace((unsigned char ) (c))
92 
93  const char STD_DATETIME_FMT[] = "%Y-%m-%d %H:%M:%S.%z";
94 #if !defined(_WIN32) && !defined(DOS32X)
95 static const char pid_config_logpath[] = "/tmp/tdsconfig.log.%d";
96 static const char freetds_conf[] = "%s/etc/freetds.conf";
97 static const char location[] = "(from $FREETDS/etc)";
98 static const char pid_logpath[] = "/tmp/freetds.log.%d";
99 static const char interfaces_path[] = "/etc/freetds";
100 #else
101 static const char pid_config_logpath[] = "c:\\tdsconfig.log.%d";
102 static const char freetds_conf [] = "%s\\freetds.conf";
103 static const char location[] = "(from $FREETDS)";
104 static const char pid_logpath[] = "c:\\freetds.log.%d";
105 static const char interfaces_path[] = "c:\\";
106 #endif
107 
108 /**
109  * \ingroup libtds
110  * \defgroup config Configuration
111  * Handle reading of configuration
112  */
113 
114 /**
115  * \addtogroup config
116  * @{
117  */
118 
119 /**
120  * tds_read_config_info() will fill the tds connection structure based on configuration
121  * information gathered in the following order:
122  * 1) Program specified in TDSLOGIN structure
123  * 2) The environment variables TDSVER, TDSDUMP, TDSPORT, TDSQUERY, TDSHOST
124  * 3) A config file with the following search order:
125  * a) a readable file specified by environment variable FREETDSCONF
126  * b) a readable file in ~/.freetds.conf
127  * c) a readable file in $prefix/etc/freetds.conf
128  * 3) ~/.interfaces if exists
129  * 4) $SYBASE/interfaces if exists
130  * 5) TDS_DEF_* default values
131  *
132  * .tdsrc and freetds.conf have been added to make the package easier to
133  * integration with various Linux and *BSD distributions.
134  */
135 TDSLOGIN *
137 {
138  TDSLOGIN *connection;
139  char *s;
140  char *path;
141  pid_t pid;
142  int opened = 0, found;
143  struct addrinfo *addrs;
144 
145  /* allocate a new structure with hard coded and build-time defaults */
146  connection = tds_alloc_login(0);
147  if (!connection || !tds_init_login(connection, locale)) {
148  tds_free_login(connection);
149  return NULL;
150  }
151 
152  s = getenv("TDSDUMPCONFIG");
153  if (s) {
154  if (*s) {
155  opened = tdsdump_open(s);
156  } else {
157  pid = getpid();
158  if (asprintf(&path, pid_config_logpath, pid) >= 0) {
159  if (*path) {
160  opened = tdsdump_open(path);
161  }
162  free(path);
163  }
164  }
165  }
166 
167  tdsdump_log(TDS_DBG_INFO1, "Getting connection information for [%s].\n",
168  tds_dstr_cstr(&login->server_name)); /* (The server name is set in login.c.) */
169 
170  /* Read the config files. */
171  tdsdump_log(TDS_DBG_INFO1, "Attempting to read conf files.\n");
172  found = tds_read_conf_file(connection, tds_dstr_cstr(&login->server_name));
173  if (!found) {
174  if (parse_server_name_for_port(connection, login)) {
175 
176  found = tds_read_conf_file(connection, tds_dstr_cstr(&connection->server_name));
177  /* do it again to really override what found in freetds.conf */
178  if (found) {
179  parse_server_name_for_port(connection, login);
180  } else if (TDS_SUCCEED(tds_lookup_host_set(tds_dstr_cstr(&connection->server_name), &connection->ip_addrs))) {
181  if (!tds_dstr_dup(&connection->server_host_name, &connection->server_name)) {
182  tds_free_login(connection);
183  return NULL;
184  }
185  found = 1;
186  }
187  }
188  }
189  if (!found) {
190  /* fallback to interfaces file */
191  tdsdump_log(TDS_DBG_INFO1, "Failed in reading conf file. Trying interface files.\n");
192  if (!tds_read_interfaces(tds_dstr_cstr(&login->server_name), connection)) {
193  tdsdump_log(TDS_DBG_INFO1, "Failed to find [%s] in configuration files; trying '%s' instead.\n",
195  if (connection->ip_addrs == NULL)
197  }
198  }
199 
200  /* Override config file settings with environment variables. */
201  tds_fix_login(connection);
202 
203  /* And finally apply anything from the login structure */
204  if (!tds_config_login(connection, login)) {
205  tds_free_login(connection);
206  return NULL;
207  }
208 
209  if (opened) {
210  char tmp[128];
211 
212  tdsdump_log(TDS_DBG_INFO1, "Final connection parameters:\n");
213  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_name", tds_dstr_cstr(&connection->server_name));
214  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_host_name", tds_dstr_cstr(&connection->server_host_name));
215 
216  for (addrs = connection->ip_addrs; addrs != NULL; addrs = addrs->ai_next)
217  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "ip_addr", tds_addrinfo2str(addrs, tmp, sizeof(tmp)));
218 
219  if (connection->ip_addrs == NULL)
220  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "ip_addr", "");
221 
222  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "instance_name", tds_dstr_cstr(&connection->instance_name));
223  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "port", connection->port);
224  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "major_version", TDS_MAJOR(connection));
225  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "minor_version", TDS_MINOR(connection));
226  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "block_size", connection->block_size);
227  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "language", tds_dstr_cstr(&connection->language));
228  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_charset", tds_dstr_cstr(&connection->server_charset));
229  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "connect_timeout", connection->connect_timeout);
230  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "client_host_name", tds_dstr_cstr(&connection->client_host_name));
231  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "client_charset", tds_dstr_cstr(&connection->client_charset));
232  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "use_utf16", connection->use_utf16);
233  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "app_name", tds_dstr_cstr(&connection->app_name));
234  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "user_name", tds_dstr_cstr(&connection->user_name));
235  /* tdsdump_log(TDS_DBG_PASSWD, "\t%20s = %s\n", "password", tds_dstr_cstr(&connection->password));
236  (no such flag yet) */
237  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "library", tds_dstr_cstr(&connection->library));
238  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "bulk_copy", (int)connection->bulk_copy);
239  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "suppress_language", (int)connection->suppress_language);
240  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "encrypt level", (int)connection->encryption_level);
241  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "query_timeout", connection->query_timeout);
242  /* tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "capabilities", tds_dstr_cstr(&connection->capabilities));
243  (not null terminated) */
244  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "database", tds_dstr_cstr(&connection->database));
245  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "dump_file", tds_dstr_cstr(&connection->dump_file));
246  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %x\n", "debug_flags", connection->debug_flags);
247  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "text_size", connection->text_size);
248  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "emul_little_endian", connection->emul_little_endian);
249  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_realm_name", tds_dstr_cstr(&connection->server_realm_name));
250  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_spn", tds_dstr_cstr(&connection->server_spn));
251  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "cafile", tds_dstr_cstr(&connection->cafile));
252  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "crlfile", tds_dstr_cstr(&connection->crlfile));
253  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "check_ssl_hostname", connection->check_ssl_hostname);
254  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "db_filename", tds_dstr_cstr(&connection->db_filename));
255  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "readonly_intent", connection->readonly_intent);
256 #ifdef HAVE_OPENSSL
257  tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "openssl_ciphers", tds_dstr_cstr(&connection->openssl_ciphers));
258 #endif
259 
260  tdsdump_close();
261  }
262 
263  /*
264  * If a dump file has been specified, start logging
265  */
266  if (!tds_dstr_isempty(&connection->dump_file) && !tdsdump_isopen()) {
267  if (connection->debug_flags)
268  tds_debug_flags = connection->debug_flags;
269  tdsdump_open(tds_dstr_cstr(&connection->dump_file));
270  }
271 
272  return connection;
273 }
274 
275 /**
276  * Fix configuration after reading it.
277  * Currently this read some environment variables and replace some options.
278  */
279 void
281 {
282  /* Now check the environment variables */
287 }
288 
289 static int
290 tds_try_conf_file(const char *path, const char *how, const char *server, TDSLOGIN * login)
291 {
292  int found = 0;
293  FILE *in;
294 
295  if ((in = fopen(path, "r")) == NULL) {
296  tdsdump_log(TDS_DBG_INFO1, "Could not open '%s' (%s).\n", path, how);
297  return found;
298  }
299 
300  tdsdump_log(TDS_DBG_INFO1, "Found conf file '%s' %s.\n", path, how);
301  found = tds_read_conf_sections(in, server, login);
302 
303  if (found) {
304  tdsdump_log(TDS_DBG_INFO1, "Success: [%s] defined in %s.\n", server, path);
305  } else {
306  tdsdump_log(TDS_DBG_INFO2, "[%s] not found.\n", server);
307  }
308 
309  fclose(in);
310 
311  return found;
312 }
313 
314 
315 /**
316  * Return filename from HOME directory
317  * @return allocated string or NULL if error
318  */
319 static char *
321 {
322  char *home, *path;
323 
324  home = tds_get_homedir();
325  if (!home)
326  return NULL;
327  if (asprintf(&path, "%s/%s", home, file) < 0)
328  path = NULL;
329  free(home);
330  return path;
331 }
332 
333 /**
334  * Read configuration info for given server
335  * return 0 on error
336  * @param login where to store configuration
337  * @param server section of file configuration that hold
338  * configuration for a server
339  */
340 int
341 tds_read_conf_file(TDSLOGIN * login, const char *server)
342 {
343  char *path = NULL;
344  char *eptr = NULL;
345  int found = 0;
346 
347  if (interf_file) {
348  found = tds_try_conf_file(interf_file, "set programmatically", server, login);
349  }
350 
351  /* FREETDSCONF env var, pkleef@openlinksw.com 01/21/02 */
352  if (!found) {
353  path = getenv("FREETDSCONF");
354  if (path) {
355  found = tds_try_conf_file(path, "(from $FREETDSCONF)", server, login);
356  } else {
357  tdsdump_log(TDS_DBG_INFO2, "... $FREETDSCONF not set. Trying $FREETDS/etc.\n");
358  }
359  }
360 
361  /* FREETDS env var, Bill Thompson 16/07/03 */
362  if (!found) {
363  eptr = getenv("FREETDS");
364  if (eptr) {
365  if (asprintf(&path, freetds_conf, eptr) >= 0) {
366  found = tds_try_conf_file(path, location, server, login);
367  free(path);
368  }
369  } else {
370  tdsdump_log(TDS_DBG_INFO2, "... $FREETDS not set. Trying $HOME.\n");
371  }
372  }
373 
374  if (!found) {
375  path = tds_get_home_file(".freetds.conf");
376  if (path) {
377  found = tds_try_conf_file(path, "(.freetds.conf)", server, login);
378  free(path);
379  } else {
380  tdsdump_log(TDS_DBG_INFO2, "... Error getting ~/.freetds.conf. Trying %s.\n", FREETDS_SYSCONFFILE);
381  }
382  }
383 
384  if (!found) {
385  found = tds_try_conf_file(FREETDS_SYSCONFFILE, "(default)", server, login);
386  }
387 
388  return found;
389 }
390 
391 static int
392 tds_read_conf_sections(FILE * in, const char *server, TDSLOGIN * login)
393 {
394  DSTR default_instance = DSTR_INITIALIZER;
395  int default_port;
396 
397  int found;
398 
400 
401  if (!server[0])
402  return 0;
403  rewind(in);
404 
405  if (!tds_dstr_dup(&default_instance, &login->instance_name))
406  return 0;
407  default_port = login->port;
408 
410  if (!login->valid_configuration) {
411  tds_dstr_free(&default_instance);
412  return 0;
413  }
414 
415  /*
416  * If both instance and port are specified and neither one came from the default, it's an error
417  * TODO: If port/instance is specified in the non-default, it has priority over the default setting.
418  * TODO: test this.
419  */
421  !(!tds_dstr_isempty(&default_instance) || default_port)) {
422  tdsdump_log(TDS_DBG_ERROR, "error: cannot specify both port %d and instance %s.\n",
424  /* tdserror(tds_get_ctx(tds), tds, TDSEPORTINSTANCE, 0); */
425  }
426  tds_dstr_free(&default_instance);
427  return found;
428 }
429 
430 static const struct {
431  char value[7];
432  unsigned char to_return;
433 } boolean_values[] = {
434  { "yes", 1 },
435  { "no", 0 },
436  { "on", 1 },
437  { "off", 0 },
438  { "true", 1 },
439  { "false", 0 }
440 };
441 
442 int
443 tds_parse_boolean(const char *value, int default_value)
444 {
445  int p;
446 
447  for (p = 0; p < TDS_VECTOR_SIZE(boolean_values); ++p) {
449  return boolean_values[p].to_return;
450  }
451  return default_value;
452 }
453 
454 int
455 tds_config_boolean(const char *option, const char *value, TDSLOGIN *login)
456 {
457  int ret = tds_parse_boolean(value, -1);
458  if (ret >= 0)
459  return ret;
460 
461  tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for boolean setting '%s'!\n",
462  value, option);
464  return 0;
465 }
466 
467 static void
469 {
471 
473  ;
478  else {
479  tdsdump_log(TDS_DBG_ERROR, "UNRECOGNIZED option value '%s' for '%s' setting!\n",
481  tdsdump_log(TDS_DBG_ERROR, "Valid settings are: ('%s', '%s', '%s')\n",
483  lvl = TDS_ENCRYPTION_REQUIRE; /* Assuming "require" is safer than "no" */
485  }
486 
487  login->encryption_level = lvl;
488 }
489 
490 /**
491  * Read a section of configuration file (INI style file)
492  * @param in configuration file
493  * @param section section to read
494  * @param tds_conf_parse callback that receive every entry in section
495  * @param param parameter to pass to callback function
496  */
497 int
498 tds_read_conf_section(FILE * in, const char *section, TDSCONFPARSE tds_conf_parse, void *param)
499 {
500  char line[256], *value;
501 #define option line
502  char *s;
503  char p;
504  int i;
505  int insection = 0;
506  int found = 0;
507 
508  tdsdump_log(TDS_DBG_INFO1, "Looking for section %s.\n", section);
509  while (fgets(line, sizeof(line), in)) {
510  s = line;
511 
512  /* skip leading whitespace */
513  while (*s && TDS_ISSPACE(*s))
514  s++;
515 
516  /* skip it if it's a comment line */
517  if (*s == ';' || *s == '#')
518  continue;
519 
520  /* read up to the = ignoring duplicate spaces */
521  p = 0;
522  i = 0;
523  while (*s && *s != '=') {
524  if (!TDS_ISSPACE(*s)) {
525  if (TDS_ISSPACE(p))
526  option[i++] = ' ';
527  option[i++] = tolower((unsigned char) *s);
528  }
529  p = *s;
530  s++;
531  }
532 
533  /* skip if empty option */
534  if (!i)
535  continue;
536 
537  /* skip the = */
538  if (*s)
539  s++;
540 
541  /* terminate the option, must be done after skipping = */
542  option[i] = '\0';
543 
544  /* skip leading whitespace */
545  while (*s && TDS_ISSPACE(*s))
546  s++;
547 
548  /* read up to a # ; or null ignoring duplicate spaces */
549  value = s;
550  p = 0;
551  i = 0;
552  while (*s && *s != ';' && *s != '#') {
553  if (!TDS_ISSPACE(*s)) {
554  if (TDS_ISSPACE(p))
555  value[i++] = ' ';
556  value[i++] = *s;
557  }
558  p = *s;
559  s++;
560  }
561  value[i] = '\0';
562 
563  if (option[0] == '[') {
564  s = strchr(option, ']');
565  if (s)
566  *s = '\0';
567  tdsdump_log(TDS_DBG_INFO1, "\tFound section %s.\n", &option[1]);
568 
569  if (!strcasecmp(section, &option[1])) {
570  tdsdump_log(TDS_DBG_INFO1, "Got a match.\n");
571  insection = 1;
572  found = 1;
573  } else {
574  insection = 0;
575  }
576  } else if (insection) {
577  tds_conf_parse(option, value, param);
578  }
579 
580  }
581  tdsdump_log(TDS_DBG_INFO1, "\tReached EOF\n");
582  return found;
583 #undef option
584 }
585 
586 /* Also used to scan ODBC.INI entries */
587 void
588 tds_parse_conf_section(const char *option, const char *value, void *param)
589 {
590  TDSLOGIN *login = (TDSLOGIN *) param;
591  void *s = param;
592 
593  tdsdump_log(TDS_DBG_INFO1, "\t%s = '%s'\n", option, value);
594 
595  if (!strcmp(option, TDS_STR_VERSION)) {
597  } else if (!strcmp(option, TDS_STR_BLKSZ)) {
598  int val = atoi(value);
599  if (val >= 512 && val < 65536)
600  login->block_size = val;
601  } else if (!strcmp(option, TDS_STR_SWAPDT)) {
602  /* this option is deprecated, just check value for compatibility */
604  } else if (!strcmp(option, TDS_GSSAPI_DELEGATION)) {
605  /* gssapi flag addition */
607  } else if (!strcmp(option, TDS_STR_DUMPFILE)) {
609  } else if (!strcmp(option, TDS_STR_DEBUGFLAGS)) {
610  char *end;
611  long flags;
612  flags = strtol(value, &end, 0);
613  if (*value != '\0' && *end == '\0' && flags > INT_MIN
614  && flags < INT_MAX)
615  login->debug_flags = (int) flags;
617  if (atoi(value))
618  login->query_timeout = atoi(value);
619  } else if (!strcmp(option, TDS_STR_CONNTIMEOUT)) {
620  if (atoi(value))
621  login->connect_timeout = atoi(value);
622  } else if (!strcmp(option, TDS_STR_HOST)) {
623  char tmp[128];
624  struct addrinfo *addrs;
625 
627  tdsdump_log(TDS_DBG_WARN, "Found host entry %s however name resolution failed. \n", value);
628  return;
629  }
630 
631  tdsdump_log(TDS_DBG_INFO1, "Found host entry %s \n", value);
633  for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next)
634  tdsdump_log(TDS_DBG_INFO1, "IP addr is %s.\n", tds_addrinfo2str(addrs, tmp, sizeof(tmp)));
635 
636  } else if (!strcmp(option, TDS_STR_PORT)) {
637  if (atoi(value))
638  login->port = atoi(value);
639  } else if (!strcmp(option, TDS_STR_EMUL_LE)) {
641  } else if (!strcmp(option, TDS_STR_TEXTSZ)) {
642  if (atoi(value))
643  login->text_size = atoi(value);
644  } else if (!strcmp(option, TDS_STR_CHARSET)) {
647  } else if (!strcmp(option, TDS_STR_CLCHARSET)) {
649  tdsdump_log(TDS_DBG_INFO1, "tds_parse_conf_section: %s is %s.\n", option, tds_dstr_cstr(&login->client_charset));
650  } else if (!strcmp(option, TDS_STR_USE_UTF_16)) {
652  } else if (!strcmp(option, TDS_STR_LANGUAGE)) {
654  } else if (!strcmp(option, TDS_STR_APPENDMODE)) {
656  } else if (!strcmp(option, TDS_STR_INSTANCE)) {
658  } else if (!strcmp(option, TDS_STR_ENCRYPTION)) {
660  } else if (!strcmp(option, TDS_STR_ASA_DATABASE)) {
662  } else if (!strcmp(option, TDS_STR_USENTLMV2)) {
664  } else if (!strcmp(option, TDS_STR_USELANMAN)) {
666  } else if (!strcmp(option, TDS_STR_REALM)) {
668  } else if (!strcmp(option, TDS_STR_SPN)) {
670  } else if (!strcmp(option, TDS_STR_CAFILE)) {
672  } else if (!strcmp(option, TDS_STR_CRLFILE)) {
674  } else if (!strcmp(option, TDS_STR_CHECKSSLHOSTNAME)) {
676  } else if (!strcmp(option, TDS_STR_DBFILENAME)) {
678  } else if (!strcmp(option, TDS_STR_DATABASE)) {
680  } else if (!strcmp(option, TDS_STR_READONLY_INTENT)) {
682  tdsdump_log(TDS_DBG_FUNC, "Setting ReadOnly Intent to '%s'.\n", value);
683  } else if (!strcmp(option, TLS_STR_OPENSSL_CIPHERS)) {
685  } else {
686  tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED option '%s' ... ignoring.\n", option);
687  }
688 
689  if (login != NULL && s == NULL)
691 }
692 
693 static int
695 {
696  DSTR *res = &login->server_name;
697 
699  if (1 || tds_dstr_isempty(&connection->server_name))
700  res = tds_dstr_dup(&connection->server_name, &login->server_name);
701  }
702  if (login->tds_version)
703  connection->tds_version = login->tds_version;
704  if (res && !tds_dstr_isempty(&login->language)) {
705  res = tds_dstr_dup(&connection->language, &login->language);
706  }
707  if (res && !tds_dstr_isempty(&login->server_charset)) {
708  res = tds_dstr_dup(&connection->server_charset, &login->server_charset);
709  }
710  if (res && !tds_dstr_isempty(&login->client_charset)) {
711  res = tds_dstr_dup(&connection->client_charset, &login->client_charset);
712  tdsdump_log(TDS_DBG_INFO1, "tds_config_login: %s is %s.\n", "client_charset",
713  tds_dstr_cstr(&connection->client_charset));
714  }
715  if (!login->use_utf16)
716  connection->use_utf16 = login->use_utf16;
717  if (res && !tds_dstr_isempty(&login->database)) {
718  res = tds_dstr_dup(&connection->database, &login->database);
719  tdsdump_log(TDS_DBG_INFO1, "tds_config_login: %s is %s.\n", "database_name",
720  tds_dstr_cstr(&connection->database));
721  }
722  if (res && !tds_dstr_isempty(&login->client_host_name)) {
723  res = tds_dstr_dup(&connection->client_host_name, &login->client_host_name);
724  }
725  if (res && !tds_dstr_isempty(&login->app_name)) {
726  res = tds_dstr_dup(&connection->app_name, &login->app_name);
727  }
728  if (res && !tds_dstr_isempty(&login->user_name)) {
729  res = tds_dstr_dup(&connection->user_name, &login->user_name);
730  }
731  if (res && !tds_dstr_isempty(&login->password)) {
732  /* for security reason clear memory */
733  tds_dstr_zero(&connection->password);
734  res = tds_dstr_dup(&connection->password, &login->password);
735  }
736  if (res && !tds_dstr_isempty(&login->library)) {
737  res = tds_dstr_dup(&connection->library, &login->library);
738  }
739  if (login->encryption_level) {
740  connection->encryption_level = login->encryption_level;
741  }
742  if (login->suppress_language) {
743  connection->suppress_language = 1;
744  }
745  if (!login->bulk_copy) {
746  connection->bulk_copy = 0;
747  }
748  if (login->block_size) {
749  connection->block_size = login->block_size;
750  }
751  if (login->port)
752  connection->port = login->port;
753  if (login->connect_timeout)
754  connection->connect_timeout = login->connect_timeout;
755 
756  if (login->query_timeout)
757  connection->query_timeout = login->query_timeout;
758 
761 
762  if (res && !tds_dstr_isempty(&login->db_filename)) {
763  res = tds_dstr_dup(&connection->db_filename, &login->db_filename);
764  }
765 
766  if (res && !tds_dstr_isempty(&login->openssl_ciphers)) {
767  res = tds_dstr_dup(&connection->openssl_ciphers, &login->openssl_ciphers);
768  }
769 
770  /* copy other info not present in configuration file */
771  connection->capabilities = login->capabilities;
772 
773  if (login->readonly_intent)
774  connection->readonly_intent = login->readonly_intent;
775  connection->use_new_password = login->use_new_password;
776  if (res)
777  res = tds_dstr_dup(&connection->new_password, &login->new_password);
778 
779  return res != NULL;
780 }
781 
782 static int
784 {
785  char *s;
786  char *path;
787  pid_t pid = 0;
788 
789  if ((s = getenv("TDSDUMP"))) {
790  if (!strlen(s)) {
791  pid = getpid();
792  if (asprintf(&path, pid_logpath, pid) < 0)
793  return 0;
794  if (!tds_dstr_set(&login->dump_file, path)) {
795  free(path);
796  return 0;
797  }
798  } else {
799  if (!tds_dstr_copy(&login->dump_file, s))
800  return 0;
801  }
802  tdsdump_log(TDS_DBG_INFO1, "Setting 'dump_file' to '%s' from $TDSDUMP.\n", tds_dstr_cstr(&login->dump_file));
803  }
804  return 1;
805 }
806 static void
808 {
809  char *s;
810 
811  if ((s = getenv("TDSPORT"))) {
812  login->port = tds_lookup_port(s);
814  tdsdump_log(TDS_DBG_INFO1, "Setting 'port' to %s from $TDSPORT.\n", s);
815  }
816  return;
817 }
818 static void
820 {
821  char *tdsver;
822 
823  if ((tdsver = getenv("TDSVER"))) {
824  TDS_USMALLINT *pver = tds_config_verstr(tdsver, login);
825  tdsdump_log(TDS_DBG_INFO1, "TDS version %sset to %s from $TDSVER.\n", (pver? "":"not "), tdsver);
826 
827  }
828  return;
829 }
830 
831 /* TDSHOST env var, pkleef@openlinksw.com 01/21/02 */
832 static int
834 {
835  const char *tdshost;
836  char tmp[128];
837  struct addrinfo *addrs;
838 
839  if (!(tdshost = getenv("TDSHOST")))
840  return 1;
841 
842  if (TDS_FAILED(tds_lookup_host_set(tdshost, &login->ip_addrs))) {
843  tdsdump_log(TDS_DBG_WARN, "Name resolution failed for '%s' from $TDSHOST.\n", tdshost);
844  return 0;
845  }
846 
847  if (!tds_dstr_copy(&login->server_host_name, tdshost))
848  return 0;
849  for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) {
850  tdsdump_log(TDS_DBG_INFO1, "Setting IP Address to %s (%s) from $TDSHOST.\n",
851  tds_addrinfo2str(addrs, tmp, sizeof(tmp)), tdshost);
852  }
853  return 1;
854 }
855 #define TDS_FIND(k,b,c) tds_find(k, b, sizeof(b)/sizeof(b[0]), sizeof(b[0]), c)
856 
857 
858 static void *
859 tds_find(const void *key, const void *base, size_t nelem, size_t width,
860  int (*compar)(const void *, const void *))
861 {
862  size_t i;
863  for (i=0; i < nelem; i++) {
864  char *p = (char*)base + width * i;
865  if (0 == compar(key, p)) {
866  return p;
867  }
868  }
869  return NULL;
870 }
871 
873 {
874  const char name[6];
876 };
877 
878 static int
879 tds_vernanme_cmp(const void *key, const void *pelem)
880 {
881  return strcmp((const char *)key, ((const struct tdsvername_t *)pelem)->name);
882 }
883 
884 /**
885  * Set TDS version from given string
886  * @param tdsver tds string version
887  * @param login where to store information
888  * @return as encoded hex value: high nybble major, low nybble minor.
889  */
891 tds_config_verstr(const char *tdsver, TDSLOGIN * login)
892 {
893  static const struct tdsvername_t tds_versions[] =
894  { { "0", 0x000 }
895  , {"auto", 0x000 }
896  , { "4.2", 0x402 }
897  , { "4.2", 0x402 }
898  , { "46", 0x406 }
899  , { "4.6", 0x406 }
900  , { "50", 0x500 }
901  , { "5.0", 0x500 }
902  , { "70", 0x700 }
903  , { "7.0", 0x700 }
904  , { "80", 0x701 }
905  , { "8.0", 0x701 }
906  , { "7.1", 0x701 }
907  , { "7.2", 0x702 }
908  , { "7.3", 0x703 }
909  , { "7.4", 0x704 }
910  };
911  const struct tdsvername_t *pver;
912 
913  if (!login) {
914  assert(login);
915  return NULL;
916  }
917 
918  if ((pver = (const struct tdsvername_t *) TDS_FIND(tdsver, tds_versions, tds_vernanme_cmp)) == NULL) {
919  tdsdump_log(TDS_DBG_INFO1, "error: no such version: %s\n", tdsver);
920  return NULL;
921  }
922 
923  login->tds_version = pver->version;
924  tdsdump_log(TDS_DBG_INFO1, "Setting tds version to %s (0x%0x).\n", tdsver, pver->version);
925 
926  return &login->tds_version;
927 }
928 
929 /**
930  * Set the full name of interface file
931  * @param interf file name
932  */
933 TDSRET
934 tds_set_interfaces_file_loc(const char *interf)
935 {
936  /* Free it if already set */
937  if (interf_file != NULL)
939  /* If no filename passed, leave it NULL */
940  if ((interf == NULL) || (interf[0] == '\0')) {
941  return TDS_SUCCESS;
942  }
943  /* Set to new value */
944  if ((interf_file = strdup(interf)) == NULL) {
945  return TDS_FAIL;
946  }
947  return TDS_SUCCESS;
948 }
949 
950 /**
951  * Get the IP address for a hostname. Store server's IP address
952  * in the string 'ip' in dotted-decimal notation. (The "hostname" might itself
953  * be a dotted-decimal address.
954  *
955  * If we can't determine the IP address then 'ip' will be set to empty
956  * string.
957  */
958 /* TODO callers seem to set always connection info... change it */
959 struct addrinfo *
960 tds_lookup_host(const char *servername) /* (I) name of the server */
961 {
962  struct addrinfo hints, *addr = NULL;
963  assert(servername != NULL);
964 
965  memset(&hints, '\0', sizeof(hints));
966  hints.ai_family = AF_UNSPEC;
967  hints.ai_socktype = SOCK_STREAM;
968 
969 #ifdef AI_ADDRCONFIG
970  hints.ai_flags |= AI_ADDRCONFIG;
971 #endif
972 
973  if (getaddrinfo(servername, NULL, &hints, &addr))
974  return NULL;
975  return addr;
976 }
977 
978 TDSRET
979 tds_lookup_host_set(const char *servername, struct addrinfo **addr)
980 {
981  struct addrinfo *newaddr;
982  assert(servername != NULL && addr != NULL);
983 
984  if ((newaddr = tds_lookup_host(servername)) != NULL) {
985  if (*addr != NULL)
986  freeaddrinfo(*addr);
987  *addr = newaddr;
988  return TDS_SUCCESS;
989  }
990  return TDS_FAIL;
991 }
992 
993 /**
994  * Given a portname lookup the port.
995  *
996  * If we can't determine the port number then return 0.
997  */
998 static int
999 tds_lookup_port(const char *portname)
1000 {
1001  int num = atoi(portname);
1002  if (!num)
1003  num = tds_getservice(portname);
1004  return num;
1005 }
1006 
1007 /* TODO same code in convert.c ?? */
1008 static int
1009 hexdigit(int c)
1010 {
1011  if (c >= '0' && c <= '9')
1012  return c - '0';
1013  /* ascii optimization, 'A' -> 'a', 'a' -> 'a' */
1014  c |= 0x20;
1015  if (c >= 'a' && c <= 'f')
1016  return c - 'a' + 10;
1017  return 0; /* bad hex digit */
1018 }
1019 
1020 static int
1021 hex2num(char *hex)
1022 {
1023  return hexdigit(hex[0]) * 16 + hexdigit(hex[1]);
1024 }
1025 
1026 /**
1027  * Open and read the file 'file' searching for a logical server
1028  * by the name of 'host'. If one is found then lookup
1029  * the IP address and port number and store them in 'login'
1030  *
1031  * \param dir name of base directory for interface file
1032  * \param file name of the interface file
1033  * \param host logical host to search for
1034  * \return 0 if not fount 1 if found
1035  */
1036 static int
1037 search_interface_file(TDSLOGIN * login, const char *dir, const char *file, const char *host)
1038 {
1039  char *pathname;
1040  char line[255];
1041  char tmp_ip[sizeof(line)];
1042  char tmp_port[sizeof(line)];
1043  char tmp_ver[sizeof(line)];
1044  FILE *in;
1045  char *field;
1046  int found = 0;
1047  int server_found = 0;
1048  char *lasts;
1049 
1050  line[0] = '\0';
1051  tmp_ip[0] = '\0';
1052  tmp_port[0] = '\0';
1053  tmp_ver[0] = '\0';
1054 
1055  tdsdump_log(TDS_DBG_INFO1, "Searching interfaces file %s/%s.\n", dir, file);
1056  pathname = tds_new(char, strlen(dir) + strlen(file) + 10);
1057  if (!pathname)
1058  return 0;
1059 
1060  /*
1061  * create the full pathname to the interface file
1062  */
1063  if (file[0] == '\0') {
1064  pathname[0] = '\0';
1065  } else {
1066  if (dir[0] == '\0') {
1067  pathname[0] = '\0';
1068  } else {
1069  strcpy(pathname, dir);
1070  strcat(pathname, TDS_SDIR_SEPARATOR);
1071  }
1072  strcat(pathname, file);
1073  }
1074 
1075 
1076  /*
1077  * parse the interfaces file and find the server and port
1078  */
1079  if ((in = fopen(pathname, "r")) == NULL) {
1080  tdsdump_log(TDS_DBG_INFO1, "Couldn't open %s.\n", pathname);
1081  free(pathname);
1082  return 0;
1083  }
1084  tdsdump_log(TDS_DBG_INFO1, "Interfaces file %s opened.\n", pathname);
1085 
1086  while (fgets(line, sizeof(line) - 1, in)) {
1087  if (line[0] == '#')
1088  continue; /* comment */
1089 
1090  if (!TDS_ISSPACE(line[0])) {
1091  field = strtok_r(line, "\n\t ", &lasts);
1092  if (!strcmp(field, host)) {
1093  found = 1;
1094  tdsdump_log(TDS_DBG_INFO1, "Found matching entry for host %s.\n", host);
1095  } else
1096  found = 0;
1097  } else if (found && TDS_ISSPACE(line[0])) {
1098  field = strtok_r(line, "\n\t ", &lasts);
1099  if (field != NULL && !strcmp(field, "query")) {
1100  field = strtok_r(NULL, "\n\t ", &lasts); /* tcp or tli */
1101  if (!strcmp(field, "tli")) {
1102  tdsdump_log(TDS_DBG_INFO1, "TLI service.\n");
1103  field = strtok_r(NULL, "\n\t ", &lasts); /* tcp */
1104  field = strtok_r(NULL, "\n\t ", &lasts); /* device */
1105  field = strtok_r(NULL, "\n\t ", &lasts); /* host/port */
1106  if (strlen(field) >= 18) {
1107  sprintf(tmp_port, "%d", hex2num(&field[6]) * 256 + hex2num(&field[8]));
1108  sprintf(tmp_ip, "%d.%d.%d.%d", hex2num(&field[10]),
1109  hex2num(&field[12]), hex2num(&field[14]), hex2num(&field[16]));
1110  tdsdump_log(TDS_DBG_INFO1, "tmp_port = %s. tmp_ip = %s.\n", tmp_port, tmp_ip);
1111  }
1112  } else {
1113  field = strtok_r(NULL, "\n\t ", &lasts); /* ether */
1114  strcpy(tmp_ver, field);
1115  field = strtok_r(NULL, "\n\t ", &lasts); /* host */
1116  strcpy(tmp_ip, field);
1117  tdsdump_log(TDS_DBG_INFO1, "host field %s.\n", tmp_ip);
1118  field = strtok_r(NULL, "\n\t ", &lasts); /* port */
1119  strcpy(tmp_port, field);
1120  } /* else */
1121  server_found = 1;
1122  } /* if */
1123  } /* else if */
1124  } /* while */
1125  fclose(in);
1126  free(pathname);
1127 
1128 
1129  /*
1130  * Look up the host and service
1131  */
1132  if (server_found) {
1133 
1134  if (TDS_SUCCEED(tds_lookup_host_set(tmp_ip, &login->ip_addrs))) {
1135  struct addrinfo *addrs;
1136  if (!tds_dstr_copy(&login->server_host_name, tmp_ip))
1137  return 0;
1138  for (addrs = login->ip_addrs; addrs != NULL; addrs = addrs->ai_next) {
1139  tdsdump_log(TDS_DBG_INFO1, "Resolved IP as '%s'.\n",
1140  tds_addrinfo2str(login->ip_addrs, line, sizeof(line)));
1141  }
1142  } else {
1143  tdsdump_log(TDS_DBG_WARN, "Name resolution failed for IP '%s'.\n", tmp_ip);
1144  }
1145 
1146  if (tmp_port[0])
1147  login->port = tds_lookup_port(tmp_port);
1148  if (tmp_ver[0])
1149  tds_config_verstr(tmp_ver, login);
1150  }
1151  return server_found;
1152 } /* search_interface_file() */
1153 
1154 /**
1155  * Try to find the IP number and port for a (possibly) logical server name.
1156  *
1157  * @note This function uses only the interfaces file and is deprecated.
1158  */
1159 static int
1160 tds_read_interfaces(const char *server, TDSLOGIN * login)
1161 {
1162  int found = 0;
1163 
1164  /* read $SYBASE/interfaces */
1165 
1166  if (!server || !server[0]) {
1167  server = getenv("TDSQUERY");
1168  if (!server || !server[0])
1169  server = "SYBASE";
1170  tdsdump_log(TDS_DBG_INFO1, "Setting server to %s from $TDSQUERY.\n", server);
1171 
1172  }
1173  tdsdump_log(TDS_DBG_INFO1, "Looking for server %s....\n", server);
1174 
1175  /*
1176  * Look for the server in the interf_file iff interf_file has been set.
1177  */
1178  if (interf_file) {
1179  tdsdump_log(TDS_DBG_INFO1, "Looking for server in file %s.\n", interf_file);
1180  found = search_interface_file(login, "", interf_file, server);
1181  }
1182 
1183  /*
1184  * if we haven't found the server yet then look for a $HOME/.interfaces file
1185  */
1186  if (!found) {
1187  char *path = tds_get_home_file(".interfaces");
1188 
1189  if (path) {
1190  tdsdump_log(TDS_DBG_INFO1, "Looking for server in %s.\n", path);
1191  found = search_interface_file(login, "", path, server);
1192  free(path);
1193  }
1194  }
1195 
1196  /*
1197  * if we haven't found the server yet then look in $SYBBASE/interfaces file
1198  */
1199  if (!found) {
1200  const char *sybase = getenv("SYBASE");
1201 #ifdef __VMS
1202  /* We've got to be in unix syntax for later slash-joined concatenation. */
1203  #include <unixlib.h>
1204  const char *unixspec = decc$translate_vms(sybase);
1205  if ( (int)unixspec != 0 && (int)unixspec != -1 ) sybase = unixspec;
1206 #endif
1207  if (!sybase || !sybase[0])
1208  sybase = interfaces_path;
1209 
1210  tdsdump_log(TDS_DBG_INFO1, "Looking for server in %s/interfaces.\n", sybase);
1211  found = search_interface_file(login, sybase, "interfaces", server);
1212  }
1213 
1214  /*
1215  * If we still don't have the server and port then assume the user
1216  * typed an actual server host name.
1217  */
1218  if (!found) {
1219  int ip_port;
1220  const char *env_port;
1221 
1222  /*
1223  * Make a guess about the port number
1224  */
1225 
1226  if (login->port == 0) {
1227  /*
1228  * Not set in the [global] section of the
1229  * configure file, take a guess.
1230  */
1231  ip_port = TDS_DEF_PORT;
1232  } else {
1233  /*
1234  * Preserve setting from the [global] section
1235  * of the configure file.
1236  */
1237  ip_port = login->port;
1238  }
1239  if ((env_port = getenv("TDSPORT")) != NULL) {
1240  ip_port = tds_lookup_port(env_port);
1241  tdsdump_log(TDS_DBG_INFO1, "Setting 'ip_port' to %s from $TDSPORT.\n", env_port);
1242  } else
1243  tdsdump_log(TDS_DBG_INFO1, "Setting 'ip_port' to %d as a guess.\n", ip_port);
1244 
1245  /*
1246  * look up the host
1247  */
1248 
1250  if (!tds_dstr_copy(&login->server_host_name, server))
1251  return 0;
1252 
1253  if (ip_port)
1254  login->port = ip_port;
1255  }
1256 
1257  return found;
1258 }
1259 
1260 /**
1261  * Check the server name to find port info first
1262  * Warning: connection-> & login-> are all modified when needed
1263  * \return 1 when found, else 0
1264  */
1265 static int
1267 {
1268  const char *pSep;
1269  const char *server;
1270 
1271  /* seek the ':' in login server_name */
1272  server = tds_dstr_cstr(&login->server_name);
1273 
1274  /* IPv6 address can be quoted */
1275  if (server[0] == '[') {
1276  pSep = strstr(server, "]:");
1277  if (pSep)
1278  ++pSep;
1279  } else {
1280  pSep = strrchr(server, ':');
1281  }
1282 
1283  if (pSep && pSep != server) { /* yes, i found it! */
1284  /* modify connection-> && login->server_name & ->port */
1285  login->port = connection->port = atoi(pSep + 1);
1286  tds_dstr_empty(&connection->instance_name);
1287  } else {
1288  /* handle instance name */
1289  pSep = strrchr(server, '\\');
1290  if (!pSep || pSep == server)
1291  return 0;
1292 
1293  if (!tds_dstr_copy(&connection->instance_name, pSep + 1))
1294  return 0;
1295  connection->port = 0;
1296  }
1297 
1298  if (!tds_dstr_copyn(&connection->server_name, server, pSep - server))
1299  return 0;
1300 
1301  return 1;
1302 }
1303 
1304 /**
1305  * Return a structure capturing the compile-time settings provided to the
1306  * configure script.
1307  */
1308 
1311 {
1312  static const TDS_COMPILETIME_SETTINGS settings = {
1315  , "unknown" /* need fancy script in makefile */
1316 # ifdef MSDBLIB
1317  , 1
1318 # else
1319  , 0
1320 # endif
1321 # ifdef TDS_SYBASE_COMPAT
1322  , 1
1323 # else
1324  , 0
1325 # endif
1326 # ifdef _REENTRANT
1327  , 1
1328 # else
1329  , 0
1330 # endif
1331 # ifdef HAVE_ICONV
1332  , 1
1333 # else
1334  , 0
1335 # endif
1336 # ifdef TDS42
1337  , "4.2"
1338 # elif TDS46
1339  , "4.6"
1340 # elif TDS50
1341  , "5.0"
1342 # elif TDS70
1343  , "7.0"
1344 # elif TDS71
1345  , "7.1"
1346 # elif TDS72
1347  , "7.2"
1348 # elif TDS73
1349  , "7.3"
1350 # elif TDS74
1351  , "7.4"
1352 # else
1353  , "auto"
1354 # endif
1355 # ifdef IODBC
1356  , 1
1357 # else
1358  , 0
1359 # endif
1360 # ifdef UNIXODBC
1361  , 1
1362 # else
1363  , 0
1364 # endif
1365 # ifdef HAVE_OPENSSL
1366  , 1
1367 # else
1368  , 0
1369 # endif
1370 # ifdef HAVE_GNUTLS
1371  , 1
1372 # else
1373  , 0
1374 # endif
1375 # if ENABLE_ODBC_MARS
1376  , 1
1377 # else
1378  , 0
1379 # endif
1380  };
1381 
1382  assert(settings.tdsver);
1383 
1384  return &settings;
1385 }
1386 
1387 /** @} */
static uch flags
#define strcat(s, k)
#define FREETDS_SYSCONFFILE
Definition: configs.h:39
#define FREETDS_SYSCONFDIR
Definition: sysconfdir.h:2
#define TDS_SDIR_SEPARATOR
#define TDS_FAIL
Definition: tds.h:204
#define TDS_STR_DUMPFILE
Definition: tds.h:512
#define tds_new(type, n)
Definition: tds.h:1392
#define TDS_STR_READONLY_INTENT
Definition: tds.h:555
#define TDS_STR_PORT
Definition: tds.h:520
#define TDS_FAILED(rc)
Definition: tds.h:206
#define TDS_STR_CLCHARSET
Definition: tds.h:525
#define TDS_STR_VERSION
Definition: tds.h:509
#define TDS_STR_INSTANCE
Definition: tds.h:530
#define TDS_MINOR(x)
Definition: tds.h:1715
#define tdsdump_log
Definition: tds.h:1561
#define TDS_DBG_INFO2
Definition: tds.h:899
#define TDS_STR_CHECKSSLHOSTNAME
Definition: tds.h:551
#define TDS_DEF_PORT
Definition: tds.h:505
#define TDS_DBG_INFO1
Definition: tds.h:900
#define TDS_DBG_WARN
Definition: tds.h:902
#define TDS_MAJOR(x)
Definition: tds.h:1714
#define TDS_STR_CRLFILE
Definition: tds.h:549
void(* TDSCONFPARSE)(const char *option, const char *value, void *param)
Definition: tds.h:1304
#define TDS_STR_ASA_DATABASE
Definition: tds.h:531
#define TDS_STR_ENCRYPTION_REQUEST
Definition: tds.h:538
#define TLS_STR_OPENSSL_CIPHERS
Definition: tds.h:557
@ TDSEINTF
Definition: tds.h:311
#define TDS_STR_BLKSZ
Definition: tds.h:510
#define TDS_VECTOR_SIZE(x)
Definition: tds.h:360
#define TDS_STR_ENCRYPTION_OFF
Definition: tds.h:537
#define TDS_STR_EMUL_LE
Definition: tds.h:523
#define TDS_STR_DEBUGFLAGS
Definition: tds.h:514
#define TDS_STR_ENCRYPTION
Definition: tds.h:533
#define TDS_STR_DATABASE
Definition: tds.h:532
#define TDS_STR_SWAPDT
Definition: tds.h:511
#define TDS_STR_USELANMAN
Definition: tds.h:535
#define TDS_STR_CONNTIMEOUT
Definition: tds.h:517
int TDSRET
Definition: tds.h:201
#define TDS_STR_APPENDMODE
Definition: tds.h:528
@ TDS_ENCRYPTION_REQUEST
Definition: tds.h:356
@ TDS_ENCRYPTION_OFF
Definition: tds.h:356
@ TDS_ENCRYPTION_REQUIRE
Definition: tds.h:356
#define TDS_STR_USENTLMV2
Definition: tds.h:534
tds_sysdep_uint16_type TDS_USMALLINT
Definition: tds.h:148
#define TDS_STR_TIMEOUT
Definition: tds.h:515
#define TDS_DBG_ERROR
Definition: tds.h:903
#define TDS_GSSAPI_DELEGATION
Definition: tds.h:541
#define TDS_SUCCESS
Definition: tds.h:203
#define TDS_STR_TEXTSZ
Definition: tds.h:521
#define TDS_STR_LANGUAGE
Definition: tds.h:527
#define TDS_STR_REALM
Definition: tds.h:543
#define TDS_STR_DBFILENAME
Definition: tds.h:553
#define TDS_SUCCEED(rc)
Definition: tds.h:207
#define TDS_ZERO_FREE(x)
Definition: tds.h:359
#define tds_get_ctx(tds)
Definition: tds.h:1294
#define TDS_STR_CAFILE
Definition: tds.h:547
#define TDS_STR_CHARSET
Definition: tds.h:524
#define TDS_STR_SPN
Definition: tds.h:545
#define TDS_STR_QUERY_TIMEOUT
Definition: tds.h:516
#define TDS_STR_ENCRYPTION_REQUIRE
Definition: tds.h:539
#define TDS_STR_HOST
Definition: tds.h:519
#define TDS_DBG_FUNC
Definition: tds.h:898
#define TDS_STR_USE_UTF_16
Definition: tds.h:526
enum tds_encryption_level TDS_ENCRYPTION_LEVEL
static char tmp[3200]
Definition: utf8.c:42
#define asprintf
Definition: replacements.h:54
#define strtok_r
Definition: replacements.h:68
#define getaddrinfo(n, s, h, r)
Definition: replacements.h:99
#define addrinfo
Definition: replacements.h:98
#define freeaddrinfo(a)
Definition: replacements.h:101
static const char pid_config_logpath[]
Definition: config.c:95
const char STD_DATETIME_FMT[]
Definition: config.c:93
static const char freetds_conf[]
Definition: config.c:96
static const char pid_logpath[]
Definition: config.c:98
static const char location[]
Definition: config.c:97
#define TDS_ISSPACE(c)
Definition: config.c:91
static const char interfaces_path[]
Definition: config.c:99
char value[7]
Definition: config.c:431
static char * interf_file
Definition: config.c:89
#define option
unsigned char to_return
Definition: config.c:432
static TDSSOCKET * tds
Definition: collations.c:37
static TDSLOGIN * login
Definition: dataread.c:31
#define tds_free_login
#define tdsdump_isopen
#define tds_init_login
#define tds_alloc_login
#define tds_g_append_mode
#define tds_getservice
#define tds_addrinfo2str
#define tdsdump_open
#define tdsdump_close
#define tds_debug_flags
#define tdserror
#define tds_get_homedir
#define NULL
Definition: ncbistd.hpp:225
static const struct @999 boolean_values[]
int tds_read_conf_file(TDSLOGIN *login, const char *server)
Read configuration info for given server return 0 on error.
Definition: config.c:341
TDSRET tds_lookup_host_set(const char *servername, struct addrinfo **addr)
Definition: config.c:979
static int tds_vernanme_cmp(const void *key, const void *pelem)
Definition: config.c:879
static int hex2num(char *hex)
Definition: config.c:1021
static int tds_try_conf_file(const char *path, const char *how, const char *server, TDSLOGIN *login)
Definition: config.c:290
void tds_parse_conf_section(const char *option, const char *value, void *param)
Definition: config.c:588
static void tds_config_encryption(const char *value, TDSLOGIN *login)
Definition: config.c:468
static int tds_lookup_port(const char *portname)
Given a portname lookup the port.
Definition: config.c:999
TDSRET tds_set_interfaces_file_loc(const char *interf)
Set the full name of interface file.
Definition: config.c:934
int tds_read_conf_section(FILE *in, const char *section, TDSCONFPARSE tds_conf_parse, void *param)
Read a section of configuration file (INI style file)
Definition: config.c:498
static int tds_read_interfaces(const char *server, TDSLOGIN *login)
Try to find the IP number and port for a (possibly) logical server name.
Definition: config.c:1160
static void tds_config_env_tdsver(TDSLOGIN *login)
Definition: config.c:819
const TDS_COMPILETIME_SETTINGS * tds_get_compiletime_settings(void)
Return a structure capturing the compile-time settings provided to the configure script.
Definition: config.c:1310
static int tds_config_env_tdsdump(TDSLOGIN *login)
Definition: config.c:783
static int tds_config_login(TDSLOGIN *connection, TDSLOGIN *login)
Definition: config.c:694
TDSLOGIN * tds_read_config_info(TDSSOCKET *tds, TDSLOGIN *login, TDSLOCALE *locale)
tds_read_config_info() will fill the tds connection structure based on configuration information gath...
Definition: config.c:136
static void tds_config_env_tdsport(TDSLOGIN *login)
Definition: config.c:807
static int hexdigit(int c)
Definition: config.c:1009
struct addrinfo * tds_lookup_host(const char *servername)
Get the IP address for a hostname.
Definition: config.c:960
int tds_config_boolean(const char *option, const char *value, TDSLOGIN *login)
Definition: config.c:455
int tds_parse_boolean(const char *value, int default_value)
Definition: config.c:443
static int tds_read_conf_sections(FILE *in, const char *server, TDSLOGIN *login)
Definition: config.c:392
static int parse_server_name_for_port(TDSLOGIN *connection, TDSLOGIN *login)
Check the server name to find port info first Warning: connection-> & login-> are all modified when n...
Definition: config.c:1266
static void * tds_find(const void *key, const void *base, size_t nelem, size_t width, int(*compar)(const void *, const void *))
Definition: config.c:859
static int tds_config_env_tdshost(TDSLOGIN *login)
Definition: config.c:833
static int search_interface_file(TDSLOGIN *login, const char *dir, const char *file, const char *host)
Open and read the file 'file' searching for a logical server by the name of 'host'.
Definition: config.c:1037
#define TDS_FIND(k, b, c)
Definition: config.c:855
void tds_fix_login(TDSLOGIN *login)
Fix configuration after reading it.
Definition: config.c:280
TDS_USMALLINT * tds_config_verstr(const char *tdsver, TDSLOGIN *login)
Set TDS version from given string.
Definition: config.c:891
static char * tds_get_home_file(const char *file)
Return filename from HOME directory.
Definition: config.c:320
static const char * tds_dstr_cstr(DSTR *s)
Returns a C version (NUL terminated string) of dstr.
Definition: string.h:66
void tds_dstr_zero(DSTR *s)
clear all string filling with zeroes (mainly for security reason)
Definition: tdsstring.c:56
#define tds_dstr_empty(s)
Make a string empty.
Definition: string.h:79
DSTR * tds_dstr_dup(DSTR *s, const DSTR *src) TDS_WUR
Duplicate a string from another dynamic string.
Definition: tdsstring.c:135
#define DSTR_INITIALIZER
Initializer, used to initialize string like in the following example.
Definition: string.h:37
DSTR * tds_dstr_copyn(DSTR *s, const char *src, size_t length) TDS_WUR
Set string to a given buffer of characters.
Definition: tdsstring.c:78
DSTR * tds_dstr_set(DSTR *s, char *src) TDS_WUR
set a string from another buffer.
Definition: tdsstring.c:108
void tds_dstr_free(DSTR *s)
free string
Definition: tdsstring.c:63
DSTR * tds_dstr_copy(DSTR *s, const char *src) TDS_WUR
copy a string from another
Definition: tdsstring.c:123
static int tds_dstr_isempty(DSTR *s)
test if string is empty
Definition: string.h:48
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
#define TDS_VERSION_NO
Definition: version.h:25
FILE * file
int i
static void hex(unsigned char c)
Definition: mdb_dump.c:56
const struct ncbi::grid::netcache::search::fields::KEY key
int strcmp(const char *str1, const char *str2)
Definition: odbc_utils.hpp:160
#define strdup
Definition: ncbi_ansi_ext.h:70
#define strcasecmp
int tolower(Uchar c)
Definition: ncbictype.hpp:72
std::istream & in(std::istream &in_, double &x_)
static char * locale
Definition: pcregrep.c:149
#define assert(x)
Definition: srv_diag.hpp:58
A structure to hold all the compile-time settings.
Definition: tds.h:95
const char * tdsver
Definition: tds.h:103
Structure to hold a string.
Definition: tds.h:116
Definition: tds.h:584
unsigned int use_ntlmv2
Definition: tds.h:628
unsigned int use_new_password
Definition: tds.h:632
TDS_INT query_timeout
Definition: tds.h:608
DSTR crlfile
certificate revocation file
Definition: tds.h:598
unsigned int check_ssl_hostname
Definition: tds.h:634
DSTR server_realm_name
server realm name (in freetds.conf)
Definition: tds.h:594
DSTR database
Definition: tds.h:611
DSTR client_charset
Definition: tds.h:610
DSTR user_name
account for login
Definition: tds.h:601
TDS_INT connect_timeout
Definition: tds.h:591
unsigned int gssapi_use_delegation
Definition: tds.h:627
struct addrinfo * ip_addrs
ip(s) of server
Definition: tds.h:613
DSTR password
password of account login
Definition: tds.h:602
DSTR db_filename
database filename to attach (MSSQL)
Definition: tds.h:596
TDS_CAPABILITIES capabilities
Definition: tds.h:609
unsigned int readonly_intent
Definition: tds.h:635
TDS_TINYINT encryption_level
Definition: tds.h:606
DSTR client_host_name
Definition: tds.h:592
DSTR dump_file
Definition: tds.h:616
unsigned int valid_configuration
Definition: tds.h:633
DSTR server_name
server name (in freetds.conf)
Definition: tds.h:585
DSTR instance_name
Definition: tds.h:615
DSTR server_charset
charset of server e.g.
Definition: tds.h:590
DSTR language
Definition: tds.h:589
int debug_flags
Definition: tds.h:617
TDS_USMALLINT tds_version
TDS version.
Definition: tds.h:587
DSTR new_password
new password to set (TDS 7.2+)
Definition: tds.h:603
unsigned int use_utf16
Definition: tds.h:631
unsigned int use_lanman
Definition: tds.h:629
unsigned int suppress_language
Definition: tds.h:625
int text_size
Definition: tds.h:618
DSTR server_host_name
Definition: tds.h:593
unsigned int emul_little_endian
Definition: tds.h:626
DSTR openssl_ciphers
Definition: tds.h:599
unsigned int bulk_copy
if bulk copy should be enabled
Definition: tds.h:624
DSTR cafile
certificate authorities file
Definition: tds.h:597
DSTR server_spn
server SPN (in freetds.conf)
Definition: tds.h:595
int port
port of database service
Definition: tds.h:586
int block_size
Definition: tds.h:588
DSTR library
Definition: tds.h:605
DSTR app_name
Definition: tds.h:600
Information for a server connection.
Definition: tds.h:1211
TDS_USMALLINT version
Definition: config.c:875
const char name[6]
Definition: config.c:874
void free(voidpf ptr)
Modified on Wed May 01 14:24:40 2024 by modify_doxy.py rev. 669887