Merge branch 'debian' into hcoop_489
[hcoop/debian/exim4.git] / src / lookups / lf_sqlperform.c
CommitLineData
420a0d19
CE
1/*************************************************
2* Exim - an Internet mail transport agent *
3*************************************************/
4
2813c06e 5/* Copyright (c) University of Cambridge 1995 - 2015 */
420a0d19
CE
6/* See the file NOTICE for conditions of use and distribution. */
7
8
9#include "../exim.h"
10#include "lf_functions.h"
11
12
13
14/*************************************************
15* Call SQL server(s) to run an actual query *
16*************************************************/
17
18/* All the SQL lookups are of the same form, with a list of servers to try
19until one can be accessed. It is now also possible to provide the server data
20as part of the query. This function manages server selection and looping; each
21lookup has its own function for actually performing the lookup.
22
23Arguments:
24 name the lookup name, e.g. "MySQL"
25 optionname the name of the servers option, e.g. "mysql_servers"
26 optserverlist the value of the servers option
27 query the query
28 result where to pass back the result
29 errmsg where to pass back an error message
2813c06e 30 do_cache to be set zero if data is changed
420a0d19
CE
31 func the lookup function to call
32
33Returns: the return from the lookup function, or DEFER
34*/
35
36int
2813c06e
CE
37lf_sqlperform(const uschar *name, const uschar *optionname,
38 const uschar *optserverlist, const uschar *query,
39 uschar **result, uschar **errmsg, uint *do_cache,
40 int(*fn)(const uschar *, uschar *, uschar **, uschar **, BOOL *, uint *))
420a0d19
CE
41{
42int sep, rc;
43uschar *server;
2813c06e 44const uschar *serverlist;
420a0d19
CE
45uschar buffer[512];
46BOOL defer_break = FALSE;
47
48DEBUG(D_lookup) debug_printf("%s query: %s\n", name, query);
49
50/* Handle queries that do not have server information at the start. */
51
52if (Ustrncmp(query, "servers", 7) != 0)
53 {
54 sep = 0;
55 serverlist = optserverlist;
56 while ((server = string_nextinlist(&serverlist, &sep, buffer,
57 sizeof(buffer))) != NULL)
58 {
59 rc = (*fn)(query, server, result, errmsg, &defer_break, do_cache);
60 if (rc != DEFER || defer_break) return rc;
61 }
62 if (optserverlist == NULL)
63 *errmsg = string_sprintf("no %s servers defined (%s option)", name,
64 optionname);
65 }
66
67/* Handle queries that do have server information at the start. */
68
69else
70 {
71 int qsep;
2813c06e
CE
72 const uschar *s, *ss;
73 const uschar *qserverlist;
420a0d19
CE
74 uschar *qserver;
75 uschar qbuffer[512];
76
77 s = query + 7;
78 while (isspace(*s)) s++;
79 if (*s++ != '=')
80 {
81 *errmsg = string_sprintf("missing = after \"servers\" in %s lookup", name);
82 return DEFER;
83 }
84 while (isspace(*s)) s++;
85
86 ss = Ustrchr(s, ';');
87 if (ss == NULL)
88 {
89 *errmsg = string_sprintf("missing ; after \"servers=\" in %s lookup",
90 name);
91 return DEFER;
92 }
93
94 if (ss == s)
95 {
96 *errmsg = string_sprintf("\"servers=\" defines no servers in \"%s\"",
97 query);
98 return DEFER;
99 }
100
101 qserverlist = string_sprintf("%.*s", ss - s, s);
102 qsep = 0;
103
104 while ((qserver = string_nextinlist(&qserverlist, &qsep, qbuffer,
105 sizeof(qbuffer))) != NULL)
106 {
107 if (Ustrchr(qserver, '/') != NULL)
108 server = qserver;
109 else
110 {
111 int len = Ustrlen(qserver);
112
113 sep = 0;
114 serverlist = optserverlist;
115 while ((server = string_nextinlist(&serverlist, &sep, buffer,
116 sizeof(buffer))) != NULL)
117 {
118 if (Ustrncmp(server, qserver, len) == 0 && server[len] == '/')
119 break;
120 }
121
122 if (server == NULL)
123 {
124 *errmsg = string_sprintf("%s server \"%s\" not found in %s", name,
125 qserver, optionname);
126 return DEFER;
127 }
128 }
129
130 rc = (*fn)(ss+1, server, result, errmsg, &defer_break, do_cache);
131 if (rc != DEFER || defer_break) return rc;
132 }
133 }
134
135return DEFER;
136}
137
138/* End of lf_sqlperform.c */