summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPhilip Hazel <ph10@hermes.cam.ac.uk>2007-08-23 10:16:51 +0000
committerPhilip Hazel <ph10@hermes.cam.ac.uk>2007-08-23 10:16:51 +0000
commitb7670459b9549ad6dcca2398580165e54b09b92d (patch)
treea697ce1627742155665310463145ff9f0bda9edb /src
parent48ed62d9a68c4e44c9fbaa6e300f88401bb32d65 (diff)
Add "server=" feature to MySQL and PostgreSQL lookups.
Diffstat (limited to 'src')
-rwxr-xr-xsrc/scripts/MakeLinks3
-rw-r--r--src/src/lookups/Makefile5
-rw-r--r--src/src/lookups/lf_functions.h5
-rw-r--r--src/src/lookups/lf_sqlperform.c139
-rw-r--r--src/src/lookups/mysql.c28
-rw-r--r--src/src/lookups/pgsql.c29
6 files changed, 160 insertions, 49 deletions
diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks
index ce125a8dd..c016e50c7 100755
--- a/src/scripts/MakeLinks
+++ b/src/scripts/MakeLinks
@@ -1,5 +1,5 @@
#!/bin/sh
-# $Cambridge: exim/src/scripts/MakeLinks,v 1.11 2007/06/26 11:16:54 ph10 Exp $
+# $Cambridge: exim/src/scripts/MakeLinks,v 1.12 2007/08/23 10:16:51 ph10 Exp $
# Script to build links for all the exim source files from the system-
# specific build directory. It should be run from within that directory.
@@ -95,6 +95,7 @@ ln -s ../../src/lookups/whoson.c whoson.c
ln -s ../../src/lookups/lf_functions.h lf_functions.h
ln -s ../../src/lookups/lf_check_file.c lf_check_file.c
ln -s ../../src/lookups/lf_quote.c lf_quote.c
+ln -s ../../src/lookups/lf_sqlperform.c lf_sqlperform.c
cd ..
diff --git a/src/src/lookups/Makefile b/src/src/lookups/Makefile
index 59237263c..fce944589 100644
--- a/src/src/lookups/Makefile
+++ b/src/src/lookups/Makefile
@@ -1,4 +1,4 @@
-# $Cambridge: exim/src/src/lookups/Makefile,v 1.5 2005/09/12 13:50:03 ph10 Exp $
+# $Cambridge: exim/src/src/lookups/Makefile,v 1.6 2007/08/23 10:16:51 ph10 Exp $
# Make file for building a library containing all the available lookups and
# calling it lookups.a. This is called from the main make file, after cd'ing
@@ -7,7 +7,7 @@
OBJ = cdb.o dbmdb.o dnsdb.o dsearch.o ibase.o ldap.o lsearch.o mysql.o nis.o \
nisplus.o oracle.o passwd.o pgsql.o spf.o sqlite.o testdb.o whoson.o \
- lf_check_file.o lf_quote.o
+ lf_check_file.o lf_quote.o lf_sqlperform.o
lookups.a: $(OBJ)
@$(RM_COMMAND) -f lookups.a
@@ -22,6 +22,7 @@ lookups.a: $(OBJ)
lf_check_file.o: $(HDRS) lf_check_file.c lf_functions.h
lf_quote.o: $(HDRS) lf_quote.c lf_functions.h
+lf_sqlperform.o: $(HDRS) lf_sqlperform.c lf_functions.h
cdb.o: $(HDRS) cdb.c cdb.h
dbmdb.o: $(HDRS) dbmdb.c dbmdb.h
diff --git a/src/src/lookups/lf_functions.h b/src/src/lookups/lf_functions.h
index 0cf06a2d7..7e9dec1dd 100644
--- a/src/src/lookups/lf_functions.h
+++ b/src/src/lookups/lf_functions.h
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/lookups/lf_functions.h,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
+/* $Cambridge: exim/src/src/lookups/lf_functions.h,v 1.5 2007/08/23 10:16:51 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -12,5 +12,8 @@
extern int lf_check_file(int, uschar *, int, int, uid_t *, gid_t *, char *,
uschar **);
extern uschar *lf_quote(uschar *, uschar *, int, uschar *, int *, int *);
+extern int lf_sqlperform(uschar *, uschar *, uschar *, uschar *, uschar **,
+ uschar **, BOOL *, int(*)(uschar *, uschar *, uschar **,
+ uschar **, BOOL *, BOOL *));
/* End of lf_functions.h */
diff --git a/src/src/lookups/lf_sqlperform.c b/src/src/lookups/lf_sqlperform.c
new file mode 100644
index 000000000..2d50f70a0
--- /dev/null
+++ b/src/src/lookups/lf_sqlperform.c
@@ -0,0 +1,139 @@
+/* $Cambridge: exim/src/src/lookups/lf_sqlperform.c,v 1.1 2007/08/23 10:16:51 ph10 Exp $ */
+
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) University of Cambridge 1995 - 2007 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+
+#include "../exim.h"
+#include "lf_functions.h"
+
+
+
+/*************************************************
+* Call SQL server(s) to run an actual query *
+*************************************************/
+
+/* All the SQL lookups are of the same form, with a list of servers to try
+until one can be accessed. It is now also possible to provide the server data
+as part of the query. This function manages server selection and looping; each
+lookup has its own function for actually performing the lookup.
+
+Arguments:
+ name the lookup name, e.g. "MySQL"
+ optionname the name of the servers option, e.g. "mysql_servers"
+ optserverlist the value of the servers option
+ query the query
+ result where to pass back the result
+ errmsg where to pass back an error message
+ do_cache to be set FALSE if data is changed
+ func the lookup function to call
+
+Returns: the return from the lookup function, or DEFER
+*/
+
+int
+lf_sqlperform(uschar *name, uschar *optionname, uschar *optserverlist,
+ uschar *query, uschar **result, uschar **errmsg, BOOL *do_cache,
+ int(*fn)(uschar *, uschar *, uschar **, uschar **, BOOL *, BOOL *))
+{
+int sep, rc;
+uschar *server;
+uschar *serverlist;
+uschar buffer[512];
+BOOL defer_break = FALSE;
+
+DEBUG(D_lookup) debug_printf("%s query: %s\n", name, query);
+
+/* Handle queries that do not have server information at the start. */
+
+if (Ustrncmp(query, "servers", 7) != 0)
+ {
+ sep = 0;
+ serverlist = optserverlist;
+ while ((server = string_nextinlist(&serverlist, &sep, buffer,
+ sizeof(buffer))) != NULL)
+ {
+ rc = (*fn)(query, server, result, errmsg, &defer_break, do_cache);
+ if (rc != DEFER || defer_break) return rc;
+ }
+ if (optserverlist == NULL)
+ *errmsg = string_sprintf("no %s servers defined (%s option)", name,
+ optionname);
+ }
+
+/* Handle queries that do have server information at the start. */
+
+else
+ {
+ int qsep;
+ uschar *s, *ss;
+ uschar *qserverlist;
+ uschar *qserver;
+ uschar qbuffer[512];
+
+ s = query + 7;
+ while (isspace(*s)) s++;
+ if (*s++ != '=')
+ {
+ *errmsg = string_sprintf("missing = after \"servers\" in %s lookup", name);
+ return DEFER;
+ }
+ while (isspace(*s)) s++;
+
+ ss = Ustrchr(s, ';');
+ if (ss == NULL)
+ {
+ *errmsg = string_sprintf("missing ; after \"servers=\" in %s lookup",
+ name);
+ return DEFER;
+ }
+
+ if (ss == s)
+ {
+ *errmsg = string_sprintf("\"servers=\" defines no servers in \"%s\"",
+ query);
+ return DEFER;
+ }
+
+ qserverlist = string_sprintf("%.*s", ss - s, s);
+ qsep = 0;
+
+ while ((qserver = string_nextinlist(&qserverlist, &qsep, qbuffer,
+ sizeof(qbuffer))) != NULL)
+ {
+ if (Ustrchr(qserver, '/') != NULL)
+ server = qserver;
+ else
+ {
+ int len = Ustrlen(qserver);
+
+ sep = 0;
+ serverlist = optserverlist;
+ while ((server = string_nextinlist(&serverlist, &sep, buffer,
+ sizeof(buffer))) != NULL)
+ {
+ if (Ustrncmp(server, qserver, len) == 0 && server[len] == '/')
+ break;
+ }
+
+ if (server == NULL)
+ {
+ *errmsg = string_sprintf("%s server \"%s\" not found in %s", name,
+ qserver, optionname);
+ return DEFER;
+ }
+ }
+
+ rc = (*fn)(ss+1, server, result, errmsg, &defer_break, do_cache);
+ if (rc != DEFER || defer_break) return rc;
+ }
+ }
+
+return DEFER;
+}
+
+/* End of lf_sqlperform.c */
diff --git a/src/src/lookups/mysql.c b/src/src/lookups/mysql.c
index 56da5f95d..781b09575 100644
--- a/src/src/lookups/mysql.c
+++ b/src/src/lookups/mysql.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/lookups/mysql.c,v 1.4 2007/01/08 10:50:19 ph10 Exp $ */
+/* $Cambridge: exim/src/src/lookups/mysql.c,v 1.5 2007/08/23 10:16:51 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -338,32 +338,16 @@ else
*************************************************/
/* See local README for interface description. The handle and filename
-arguments are not used. Loop through a list of servers while the query is
-deferred with a retryable error. */
+arguments are not used. The code to loop through a list of servers while the
+query is deferred with a retryable error is now in a separate function that is
+shared with other SQL lookups. */
int
mysql_find(void *handle, uschar *filename, uschar *query, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
-int sep = 0;
-uschar *server;
-uschar *list = mysql_servers;
-uschar buffer[512];
-
-DEBUG(D_lookup) debug_printf("MYSQL query: %s\n", query);
-
-while ((server = string_nextinlist(&list, &sep, buffer, sizeof(buffer))) != NULL)
- {
- BOOL defer_break = FALSE;
- int rc = perform_mysql_search(query, server, result, errmsg, &defer_break,
- do_cache);
- if (rc != DEFER || defer_break) return rc;
- }
-
-if (mysql_servers == NULL)
- *errmsg = US"no MYSQL servers defined (mysql_servers option)";
-
-return DEFER;
+return lf_sqlperform(US"MySQL", US"mysql_servers", mysql_servers, query,
+ result, errmsg, do_cache, perform_mysql_search);
}
diff --git a/src/src/lookups/pgsql.c b/src/src/lookups/pgsql.c
index e6e8f70ba..eace0840d 100644
--- a/src/src/lookups/pgsql.c
+++ b/src/src/lookups/pgsql.c
@@ -1,4 +1,4 @@
-/* $Cambridge: exim/src/src/lookups/pgsql.c,v 1.9 2007/01/08 10:50:19 ph10 Exp $ */
+/* $Cambridge: exim/src/src/lookups/pgsql.c,v 1.10 2007/08/23 10:16:51 ph10 Exp $ */
/*************************************************
* Exim - an Internet mail transport agent *
@@ -410,33 +410,16 @@ else
*************************************************/
/* See local README for interface description. The handle and filename
-arguments are not used. Loop through a list of servers while the query is
-deferred with a retryable error. */
+arguments are not used. The code to loop through a list of servers while the
+query is deferred with a retryable error is now in a separate function that is
+shared with other SQL lookups. */
int
pgsql_find(void *handle, uschar *filename, uschar *query, int length,
uschar **result, uschar **errmsg, BOOL *do_cache)
{
-int sep = 0;
-uschar *server;
-uschar *list = pgsql_servers;
-uschar buffer[512];
-
-DEBUG(D_lookup) debug_printf("PGSQL query: %s\n", query);
-
-while ((server = string_nextinlist(&list, &sep, buffer, sizeof(buffer)))
- != NULL)
- {
- BOOL defer_break = FALSE;
- int rc = perform_pgsql_search(query, server, result, errmsg, &defer_break,
- do_cache);
- if (rc != DEFER || defer_break) return rc;
- }
-
-if (pgsql_servers == NULL)
- *errmsg = US"no PGSQL servers defined (pgsql_servers option)";
-
-return DEFER;
+return lf_sqlperform(US"PostgreSQL", US"pgsql_servers", pgsql_servers, query,
+ result, errmsg, do_cache, perform_pgsql_search);
}