summaryrefslogtreecommitdiffstats
path: root/src/lookups/lf_sqlperform.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lookups/lf_sqlperform.c')
-rw-r--r--src/lookups/lf_sqlperform.c138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/lookups/lf_sqlperform.c b/src/lookups/lf_sqlperform.c
new file mode 100644
index 0000000..9966307
--- /dev/null
+++ b/src/lookups/lf_sqlperform.c
@@ -0,0 +1,138 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) University of Cambridge 1995 - 2018 */
+/* 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 zero if data is changed
+ func the lookup function to call
+
+Returns: the return from the lookup function, or DEFER
+*/
+
+int
+lf_sqlperform(const uschar *name, const uschar *optionname,
+ const uschar *optserverlist, const uschar *query,
+ uschar **result, uschar **errmsg, uint *do_cache,
+ int(*fn)(const uschar *, uschar *, uschar **, uschar **, BOOL *, uint *))
+{
+int sep, rc;
+uschar *server;
+const 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;
+ const uschar *s, *ss;
+ const 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", (int)(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 */