Imported Upstream version 4.84
[hcoop/debian/exim4.git] / src / lookups / lf_sqlperform.c
1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
4
5 /* Copyright (c) University of Cambridge 1995 - 2009 */
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
19 until one can be accessed. It is now also possible to provide the server data
20 as part of the query. This function manages server selection and looping; each
21 lookup has its own function for actually performing the lookup.
22
23 Arguments:
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
30 do_cache to be set FALSE if data is changed
31 func the lookup function to call
32
33 Returns: the return from the lookup function, or DEFER
34 */
35
36 int
37 lf_sqlperform(uschar *name, uschar *optionname, uschar *optserverlist,
38 uschar *query, uschar **result, uschar **errmsg, BOOL *do_cache,
39 int(*fn)(uschar *, uschar *, uschar **, uschar **, BOOL *, BOOL *))
40 {
41 int sep, rc;
42 uschar *server;
43 uschar *serverlist;
44 uschar buffer[512];
45 BOOL defer_break = FALSE;
46
47 DEBUG(D_lookup) debug_printf("%s query: %s\n", name, query);
48
49 /* Handle queries that do not have server information at the start. */
50
51 if (Ustrncmp(query, "servers", 7) != 0)
52 {
53 sep = 0;
54 serverlist = optserverlist;
55 while ((server = string_nextinlist(&serverlist, &sep, buffer,
56 sizeof(buffer))) != NULL)
57 {
58 rc = (*fn)(query, server, result, errmsg, &defer_break, do_cache);
59 if (rc != DEFER || defer_break) return rc;
60 }
61 if (optserverlist == NULL)
62 *errmsg = string_sprintf("no %s servers defined (%s option)", name,
63 optionname);
64 }
65
66 /* Handle queries that do have server information at the start. */
67
68 else
69 {
70 int qsep;
71 uschar *s, *ss;
72 uschar *qserverlist;
73 uschar *qserver;
74 uschar qbuffer[512];
75
76 s = query + 7;
77 while (isspace(*s)) s++;
78 if (*s++ != '=')
79 {
80 *errmsg = string_sprintf("missing = after \"servers\" in %s lookup", name);
81 return DEFER;
82 }
83 while (isspace(*s)) s++;
84
85 ss = Ustrchr(s, ';');
86 if (ss == NULL)
87 {
88 *errmsg = string_sprintf("missing ; after \"servers=\" in %s lookup",
89 name);
90 return DEFER;
91 }
92
93 if (ss == s)
94 {
95 *errmsg = string_sprintf("\"servers=\" defines no servers in \"%s\"",
96 query);
97 return DEFER;
98 }
99
100 qserverlist = string_sprintf("%.*s", ss - s, s);
101 qsep = 0;
102
103 while ((qserver = string_nextinlist(&qserverlist, &qsep, qbuffer,
104 sizeof(qbuffer))) != NULL)
105 {
106 if (Ustrchr(qserver, '/') != NULL)
107 server = qserver;
108 else
109 {
110 int len = Ustrlen(qserver);
111
112 sep = 0;
113 serverlist = optserverlist;
114 while ((server = string_nextinlist(&serverlist, &sep, buffer,
115 sizeof(buffer))) != NULL)
116 {
117 if (Ustrncmp(server, qserver, len) == 0 && server[len] == '/')
118 break;
119 }
120
121 if (server == NULL)
122 {
123 *errmsg = string_sprintf("%s server \"%s\" not found in %s", name,
124 qserver, optionname);
125 return DEFER;
126 }
127 }
128
129 rc = (*fn)(ss+1, server, result, errmsg, &defer_break, do_cache);
130 if (rc != DEFER || defer_break) return rc;
131 }
132 }
133
134 return DEFER;
135 }
136
137 /* End of lf_sqlperform.c */