Re: ct_config set CS_IFILE property is not working?

Dariusz Ostolski <[email protected]>
Newsgroups gmane.comp.db.tds.freetds
Message-ID <[email protected]>
Hello,

On -10.01.-28163 20:59, James K. Lowden wrote:
> On Tue, 3 Jan 2012 09:07:31 +0100
> dariusz ostolski<[email protected]>  wrote:
>
>> 1. Can You confirm that I cannot set custom path to interfaces file
>> using ct_config?
> Yes.  The FreeTDS function supports only three properties,  CS_IFILE
> not among them.
Thank You for your answer.

>> 2. What alternatives do I have? I don't want to modify $SYBASE
>> environment variable and I wouldn't like to use any function outside
>> ct library?
> USTL.  There's a static constant src/tds/config.c::interfaces_path.
> Add to the case statement in ct_config, diddle just a bit with the
> logic around config.c:1095:

It should be by context so I prepared a patch that should work on a 
context.
I'm sending it to You to have a look at it.  Unfortunately I had some issues
  when I was preparing this patch. My first mistake was downloading 
packaged tgz
with sources(freetds-stable which seem to be 0-91) and making all 
changes on
this packaged sources. To be able to easily produce a patch I've got an 
idea of checkouting
a branch and use cvs diff, but it seems that tgz was produced from 
different branch(or maybe a tag).
My cvs command was:

cvs -z3 
-d:pserver:[email protected]:/cvsroot/freetds co -r 
branch-0.91 freetds

so the patch is the merge of some files from this branch and what was in 
the freetds-stable.tgz.
If You could point correct tag/branch then I'll be able to merge and 
produce correct patch. Nevertheless
Im sending it to You to have look(first review), any feedback welcome.

Regards,
Darek

_______________________________________________
FreeTDS mailing list
[email protected]
http://lists.ibiblio.org/mailman/listinfo/freetds
csifile.patch (text/x-patch, 16.3 KB)
? csifile.patch
Index: include/tds.h
===================================================================
RCS file: /cvsroot/freetds/freetds/include/tds.h,v
retrieving revision 1.352
diff -u -w -r1.352 tds.h
--- include/tds.h	30 Mar 2011 11:29:34 -0000	1.352
+++ include/tds.h	11 Jan 2012 21:54:37 -0000
@@ -21,12 +21,15 @@
 #ifndef _tds_h_
 #define _tds_h_
 
-/* $Id: tds.h,v 1.352 2011/03/30 11:29:34 freddy77 Exp $ */
+/* $Id: tds.h,v 1.352.2.4 2011/08/12 16:29:36 freddy77 Exp $ */
 
 #include <stdarg.h>
 #include <stdio.h>
 #include <time.h>
 
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif /* HAVE_NET_INET_IN_H */
 #if HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif /* HAVE_ARPA_INET_H */
@@ -812,6 +815,8 @@
 #define TDS_STR_ENCRYPTION_REQUIRE "require"
 /* Defines to enable optional GSSAPI delegation */
 #define TDS_GSSAPI_DELEGATION "enable gssapi delegation"
+/* Kerberos realm name */
+#define TDS_STR_REALM	"realm"
 
 
 /* TODO do a better check for alignment than this */
@@ -861,6 +866,7 @@
 	TDS_INT connect_timeout;
 	DSTR client_host_name;
 	DSTR server_host_name;
+	DSTR server_realm_name;		/**< server realm name (in freetds.conf) */
 	DSTR app_name;
 	DSTR user_name;	    	/**< account for login */
 	DSTR password;	    	/**< password of account login */
@@ -1270,6 +1276,8 @@
 
 struct tds_context
 {
+        /* path to alternate location of interfaces file */
+        TDS_CHAR *interfaces;       
 	TDSLOCALE *locale;
 	void *parent;
 	/* handlers */
@@ -1309,6 +1317,7 @@
 	unsigned int broken_dates:1;
 	unsigned int emul_little_endian:1;
 	unsigned int use_iconv:1;
+	unsigned int tds71rev1:1;
 
 	unsigned char *in_buf;		/**< input buffer */
 	unsigned char *out_buf;		/**< output buffer */
@@ -1397,9 +1406,9 @@
 const TDS_COMPILETIME_SETTINGS *tds_get_compiletime_settings(void);
 typedef void (*TDSCONFPARSE) (const char *option, const char *value, void *param);
 int tds_read_conf_section(FILE * in, const char *section, TDSCONFPARSE tds_conf_parse, void *parse_param);
-int tds_read_conf_file(TDSCONNECTION * connection, const char *server);
+int tds_read_conf_file(TDSCONNECTION * connection, const char *server, const char *interfaces);
 void tds_parse_conf_section(const char *option, const char *value, void *param);
-TDSCONNECTION *tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale);
+TDSCONNECTION *tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale, TDS_CHAR *interfaces);
 void tds_fix_connection(TDSCONNECTION * connection);
 TDS_USMALLINT tds_config_verstr(const char *tdsver, TDSCONNECTION * connection);
 int tds_lookup_host(const char *servername, char *ip);
@@ -1416,6 +1425,8 @@
 /*@observer@*/ const char *tds_prtype(int token);
 int tds_get_varint_size(TDSSOCKET * tds, int datatype);
 int tds_get_cardinal_type(int datatype, int usertype);
+int tds_config_set_ctxt_interfaces_file(TDSCONTEXT *ctxt, void *buffer, size_t buflen);
+int tds_config_get_ctxt_interfaces_file(TDSCONTEXT *ctxt, void *buffer, size_t buflen, int *outlen);
 
 
 
@@ -1617,6 +1628,15 @@
 #endif
 
 /* bulk.c */
+
+/** bcp direction */
+enum tds_bcp_directions
+{
+	TDS_BCP_IN = 1,
+	TDS_BCP_OUT = 2,
+	TDS_BCP_QUERYOUT = 3
+};
+
 typedef struct tds_bcpinfo
 {
 	const char *hint;
Index: src/ctlib/ct.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/ctlib/ct.c,v
retrieving revision 1.207
diff -u -w -r1.207 ct.c
--- src/ctlib/ct.c	5 Oct 2010 08:36:36 -0000	1.207
+++ src/ctlib/ct.c	11 Jan 2012 21:54:38 -0000
@@ -266,7 +266,6 @@
 	
 	ctx->tds_ctx->msg_handler = _ct_handle_server_message;
 	ctx->tds_ctx->err_handler = _ct_handle_client_message;
-
 	return CS_SUCCEED;
 }
 
@@ -610,7 +609,7 @@
 	if (!(con->tds_socket = tds_alloc_socket(ctx->tds_ctx, 512)))
 		return CS_FAIL;
 	tds_set_parent(con->tds_socket, (void *) con);
-	if (!(connection = tds_read_config_info(con->tds_socket, con->tds_login, ctx->tds_ctx->locale))) {
+	if (!(connection = tds_read_config_info(con->tds_socket, con->tds_login, ctx->tds_ctx->locale, ctx->tds_ctx->interfaces))) {
 		tds_free_socket(con->tds_socket);
 		con->tds_socket = NULL;
 		return CS_FAIL;
@@ -2380,6 +2379,41 @@
 
 }
 
+static CS_RETCODE 
+_ct_set_ifile(CS_CONTEXT * ctx, CS_VOID * buffer, CS_INT buflen)
+{
+    
+    if ( buflen==CS_UNUSED ) {
+        return CS_FAIL;
+    }
+    
+    if ( buflen==CS_NULLTERM ) {
+        buflen = strlen(buffer);
+    }
+    
+    if ( tds_config_set_ctxt_interfaces_file(ctx->tds_ctx, buffer, buflen)==TDS_SUCCEED ) {
+        return CS_SUCCEED;
+    }
+    return CS_FAIL;
+}
+
+static CS_RETCODE 
+_ct_get_ifile(CS_CONTEXT * ctx, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
+{
+    if ( buflen==CS_UNUSED ) {
+        return CS_FAIL;
+    }
+    
+    if ( buflen==CS_NULLTERM ) {
+        return CS_FAIL;
+    }
+    
+    if ( tds_config_get_ctxt_interfaces_file(ctx->tds_ctx, buffer, buflen, outlen)==TDS_SUCCEED ) {
+        return CS_SUCCEED;
+    }
+    return CS_FAIL;
+}
+
 CS_RETCODE
 ct_config(CS_CONTEXT * ctx, CS_INT action, CS_INT property, CS_VOID * buffer, CS_INT buflen, CS_INT * outlen)
 {
@@ -2392,6 +2426,21 @@
 		    CS_GET ? "CS_GET" : CS_SET ? "CS_SET" : CS_SUPPORTED ? "CS_SUPPORTED" : "CS_CLEAR", property);
 
 	switch (property) {
+        case CS_IFILE: {
+                ret = CS_FAIL;
+                    switch (action) {		
+                    case CS_SET:
+                           ret = _ct_set_ifile(ctx, buffer, buflen);
+                           break;
+                    case CS_GET:
+                           ret = _ct_get_ifile(ctx, buffer, buflen, outlen);
+                           break;
+                    default:
+                           ret = CS_FAIL;
+                    }
+                }
+		break;
+                
 	case CS_EXPOSE_FMTS:
 		switch (action) {
 		case CS_SUPPORTED:
Index: src/odbc/connectparams.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/odbc/connectparams.c,v
retrieving revision 1.88
diff -u -w -r1.88 connectparams.c
--- src/odbc/connectparams.c	9 Nov 2010 15:46:42 -0000	1.88
+++ src/odbc/connectparams.c	11 Jan 2012 21:54:38 -0000
@@ -161,7 +161,7 @@
 	if (myGetPrivateProfileString(DSN, odbc_param_Servername, tmp) > 0) {
 		freetds_conf_less = 0;
 		tds_dstr_copy(&connection->server_name, tmp);
-		tds_read_conf_file(connection, tmp);
+		tds_read_conf_file(connection, tmp, NULL);
 		if (myGetPrivateProfileString(DSN, odbc_param_Server, tmp) > 0) {
 			odbc_errs_add(errs, "HY000", "You cannot specify both SERVERNAME and SERVER");
 			return 0;
@@ -330,7 +330,7 @@
 			}
 			if (!cfgs) {
 				tds_dstr_dup(&connection->server_name, &value);
-				tds_read_conf_file(connection, tds_dstr_cstr(&value));
+				tds_read_conf_file(connection, tds_dstr_cstr(&value), NULL);
 				cfgs = CFG_SERVERNAME;
 				p = connect_string;
 				continue;
Index: src/tds/config.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/tds/config.c,v
retrieving revision 1.162
diff -u -w -r1.162 config.c
--- src/tds/config.c	9 Nov 2010 15:46:42 -0000	1.162
+++ src/tds/config.c	11 Jan 2012 21:54:38 -0000
@@ -88,7 +88,7 @@
 static void tds_config_env_tdsport(TDSCONNECTION * connection);
 static void tds_config_env_tdshost(TDSCONNECTION * connection);
 static int tds_read_conf_sections(FILE * in, const char *server, TDSCONNECTION * connection);
-static int tds_read_interfaces(const char *server, TDSCONNECTION * connection);
+static int tds_read_interfaces(const char *server, TDSCONNECTION * connection, const TDS_CHAR *interfaces);
 static int parse_server_name_for_port(TDSCONNECTION * connection, TDSLOGIN * login);
 static int tds_lookup_port(const char *portname);
 static void tds_config_encryption(const char * value, TDSCONNECTION * connection);
@@ -154,7 +154,7 @@
  * integration with various Linux and *BSD distributions.
  */
 TDSCONNECTION *
-tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale)
+tds_read_config_info(TDSSOCKET * tds, TDSLOGIN * login, TDSLOCALE * locale, TDS_CHAR *interfaces)
 {
 	TDSCONNECTION *connection;
 	char *s;
@@ -187,19 +187,26 @@
 
 	/* Read the config files. */
 	tdsdump_log(TDS_DBG_INFO1, "Attempting to read conf files.\n");
-	found = tds_read_conf_file(connection, tds_dstr_cstr(&login->server_name));
+	found = tds_read_conf_file(connection, tds_dstr_cstr(&login->server_name), interfaces);
 	if (!found) {
 		if (parse_server_name_for_port(connection, login)) {
-			found = tds_read_conf_file(connection, tds_dstr_cstr(&connection->server_name));
+			char ip_addr[256];
+
+			found = tds_read_conf_file(connection, tds_dstr_cstr(&connection->server_name), interfaces);
 			/* do it again to really override what found in freetds.conf */
-			if (found)
+			if (found) {
 				parse_server_name_for_port(connection, login);
+			} else if (tds_lookup_host(tds_dstr_cstr(&connection->server_name), ip_addr) == TDS_SUCCEED) {
+				tds_dstr_dup(&connection->server_host_name, &connection->server_name);
+				tds_dstr_copy(&connection->ip_addr, ip_addr);
+				found = 1;
+			}
 		}
 	}
 	if (!found) {
 		/* fallback to interfaces file */
 		tdsdump_log(TDS_DBG_INFO1, "Failed in reading conf file.  Trying interface files.\n");
-		if (!tds_read_interfaces(tds_dstr_cstr(&login->server_name), connection)) {
+		if (!tds_read_interfaces(tds_dstr_cstr(&login->server_name), connection, interfaces)) {
 			tdsdump_log(TDS_DBG_INFO1, "Failed to find [%s] in configuration files; trying '%s' instead.\n", 
 						   tds_dstr_cstr(&login->server_name), tds_dstr_cstr(&connection->server_name));
 			if (tds_dstr_isempty(&connection->ip_addr))
@@ -245,6 +252,7 @@
 		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "text_size", connection->text_size);
 		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "broken_dates", connection->broken_dates);
 		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %d\n", "emul_little_endian", connection->emul_little_endian);
+		tdsdump_log(TDS_DBG_INFO1, "\t%20s = %s\n", "server_realm_name", tds_dstr_cstr(&connection->server_realm_name));
 
 		tdsdump_close();
 	}
@@ -327,12 +335,17 @@
  *                     configuration for a server
  */
 int
-tds_read_conf_file(TDSCONNECTION * connection, const char *server)
+tds_read_conf_file(TDSCONNECTION * connection, const char *server, const char *interfaces)
 {
 	char *path = NULL;
 	char *eptr = NULL;
 	int found = 0;
 
+        if (interfaces) {
+                tdsdump_log(TDS_DBG_INFO1, "Looking for server in file %s.\n", interfaces);
+		found = tds_try_conf_file(interfaces, "set programmatically on a context", server, connection);
+        }
+        
 	if (interf_file) {
 		found = tds_try_conf_file(interf_file, "set programmatically", server, connection);
 	}
@@ -615,6 +628,8 @@
 		tds_dstr_copy(&connection->server_name, value);
 	} else if (!strcmp(option, TDS_STR_USENTLMV2)) {
 		connection->use_ntlmv2 = tds_config_boolean(value);
+	} else if (!strcmp(option, TDS_STR_REALM)) {
+		tds_dstr_copy(&connection->server_realm_name, value);
 	} else {
 		tdsdump_log(TDS_DBG_INFO1, "UNRECOGNIZED option '%s' ... ignoring.\n", option);
 	}
@@ -640,6 +655,11 @@
 		tdsdump_log(TDS_DBG_INFO1, "tds_config_login: %s is %s.\n", "client_charset",
 			    tds_dstr_cstr(&connection->client_charset));
 	}
+	if (!tds_dstr_isempty(&login->database)) {
+		tds_dstr_dup(&connection->database, &login->database);
+		tdsdump_log(TDS_DBG_INFO1, "tds_config_login: %s is %s.\n", "database_name",
+			    tds_dstr_cstr(&connection->database));
+	}
 	if (!tds_dstr_isempty(&login->client_host_name)) {
 		tds_dstr_dup(&connection->client_host_name, &login->client_host_name);
 	}
@@ -1009,7 +1029,7 @@
  * @note This function uses only the interfaces file and is deprecated.
  */
 static int
-tds_read_interfaces(const char *server, TDSCONNECTION * connection)
+tds_read_interfaces(const char *server, TDSCONNECTION * connection, const TDS_CHAR *interfaces)
 {
 	int found = 0;
 
@@ -1023,6 +1043,13 @@
 
 	}
 	tdsdump_log(TDS_DBG_INFO1, "Looking for server %s....\n", server);
+        /*
+	 * Look for the server in the context if has been set.
+	 */
+	if (interfaces) {
+		tdsdump_log(TDS_DBG_INFO1, "Looking for server in file %s.\n", interfaces);
+		found = search_interface_file(connection, "", interfaces, server);
+	}
 
 	/*
 	 * Look for the server in the interf_file iff interf_file has been set.
@@ -1207,4 +1234,114 @@
 	return &settings;
 }
 
+/**
+ * 
+ * @param path
+ * @param buffer
+ * @param buflen
+ * @param outlen
+ * @return 
+ */
+static int 
+tds_config_get_file(const char *path, void *buffer, size_t buflen, int *outlen)
+{
+    int len = 0;    
+    if (path) {
+        
+        len = strlen(path)+1;
+        
+        /* if outlen was given we can inform how big buffer should be allocated */
+        if (outlen) {
+            *outlen = len;
+        }
+        
+        if(buffer && buflen>=len) {
+            memcpy(buffer, path, len);            
+            return TDS_SUCCEED;
+        }
+    }
+    return TDS_FAIL;
+}
+
+/**
+ * Get the full path to configuration/interface file
+ * 
+ * @param ctxt
+ * @param buffer
+ * @param buflen
+ * @param outlen
+ * @return TDS_SUCCEED or TDS_FAIL
+ */
+int
+tds_config_get_ctxt_interfaces_file(TDSCONTEXT *ctxt, void *buffer, size_t buflen, int *outlen)
+{
+    int result = 0;
+    char *path = NULL;
+    char *eptr = NULL;
+    
+    if (ctxt && ctxt->interfaces) {        
+        return tds_config_get_file(ctxt->interfaces, buffer, buflen, outlen);
+    }
+    
+    if (interf_file) {
+        return tds_config_get_file(interf_file, buffer, buflen, outlen);            
+    }
+    
+    path = getenv("FREETDSCONF");
+    if (path) {
+        return tds_config_get_file(path, buffer, buflen, outlen);
+    }
+    
+    eptr = getenv("FREETDS");
+    if (eptr) {
+            if (asprintf(&path, freetds_conf, eptr) >= 0) {
+                    result = tds_config_get_file(path, buffer, buflen, outlen);
+                    free(path);
+                    return result;
+            }
+    }
+    
+    path = tds_get_home_file(".freetds.conf");
+    if (path) {
+            result = tds_config_get_file(path, buffer, buflen, outlen);
+            free(path);
+            return result;
+    }
+            
+    return tds_config_get_file(FREETDS_SYSCONFFILE, buffer, buflen, outlen);        
+}
+
+/**
+ * 
+ * @param ctxt
+ * @param buffer
+ * @param buflen
+ * @return 
+ */
+int
+tds_config_set_ctxt_interfaces_file(TDSCONTEXT *ctxt, void *buffer, size_t buflen)
+{
+    char *buf = buffer;
+    
+    /* Free it if already set */
+    if (ctxt->interfaces) {
+        free(ctxt->interfaces);
+        ctxt->interfaces = NULL;        
+    }
+    
+   /* If no filename passed, leave it NULL */
+    if ((buflen == 0 ) || (buffer == NULL) || (buf[0] == '\0') ) {
+            return TDS_SUCCEED;
+    }
+       
+    /* Set to new value */
+    ctxt->interfaces = calloc(buflen+1, sizeof(char));
+    if ( ctxt->interfaces == NULL ) {
+        return TDS_FAIL;
+    }
+    
+    memcpy(ctxt->interfaces, buffer, buflen);    
+    return TDS_SUCCEED;
+}
+
 /** @} */
Index: src/tds/mem.c
===================================================================
RCS file: /cvsroot/freetds/freetds/src/tds/mem.c,v
retrieving revision 1.208
diff -u -w -r1.208 mem.c
--- src/tds/mem.c	28 Sep 2010 08:20:11 -0000	1.208
+++ src/tds/mem.c	11 Jan 2012 21:54:39 -0000
@@ -53,7 +53,7 @@
 #include <dmalloc.h>
 #endif
 
-TDS_RCSID(var, "$Id: mem.c,v 1.208 2010/09/28 08:20:11 freddy77 Exp $");
+TDS_RCSID(var, "$Id: mem.c,v 1.208.2.1 2011/08/12 16:29:36 freddy77 Exp $");
 
 static void tds_free_env(TDSSOCKET * tds);
 static void tds_free_compute_results(TDSSOCKET * tds);
@@ -654,6 +654,7 @@
 	return 1;
 }
 
+
 TDSCONTEXT *
 tds_alloc_context(void * parent)
 {
@@ -682,6 +683,9 @@
 	if (!context)
 		return;
 
+        if(context->interfaces)
+            free(context->interfaces);
+                    
 	tds_free_locale(context->locale);
 	free(context);
 }
@@ -827,6 +831,7 @@
 	tds_dstr_init(&connection->dump_file);
 	tds_dstr_init(&connection->client_charset);
 	tds_dstr_init(&connection->instance_name);
+	tds_dstr_init(&connection->server_realm_name);
 
 	/* fill in all hardcoded defaults */
 	if (!tds_dstr_copy(&connection->server_name, TDS_DEF_SERVER))
@@ -1188,6 +1193,7 @@
 	tds_dstr_free(&connection->password);
 	tds_dstr_free(&connection->library);
 	tds_dstr_free(&connection->instance_name);
+	tds_dstr_init(&connection->server_realm_name);
 	free(connection);
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.