Commit | Line | Data |
---|---|---|
b7670459 PH |
1 | /************************************************* |
2 | * Exim - an Internet mail transport agent * | |
3 | *************************************************/ | |
4 | ||
f9ba5e22 | 5 | /* Copyright (c) University of Cambridge 1995 - 2018 */ |
b7670459 PH |
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 | |
14b3c5bc | 30 | do_cache to be set zero if data is changed |
b7670459 PH |
31 | func the lookup function to call |
32 | ||
33 | Returns: the return from the lookup function, or DEFER | |
34 | */ | |
35 | ||
36 | int | |
55414b25 JH |
37 | lf_sqlperform(const uschar *name, const uschar *optionname, |
38 | const uschar *optserverlist, const uschar *query, | |
14b3c5bc JH |
39 | uschar **result, uschar **errmsg, uint *do_cache, |
40 | int(*fn)(const uschar *, uschar *, uschar **, uschar **, BOOL *, uint *)) | |
b7670459 PH |
41 | { |
42 | int sep, rc; | |
43 | uschar *server; | |
55414b25 | 44 | const uschar *serverlist; |
b7670459 PH |
45 | uschar buffer[512]; |
46 | BOOL defer_break = FALSE; | |
47 | ||
48 | DEBUG(D_lookup) debug_printf("%s query: %s\n", name, query); | |
49 | ||
50 | /* Handle queries that do not have server information at the start. */ | |
51 | ||
52 | if (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 | ||
69 | else | |
70 | { | |
71 | int qsep; | |
55414b25 JH |
72 | const uschar *s, *ss; |
73 | const uschar *qserverlist; | |
b7670459 PH |
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 | ||
bb07bcd3 | 101 | qserverlist = string_sprintf("%.*s", (int)(ss - s), s); |
b7670459 PH |
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 | ||
135 | return DEFER; | |
136 | } | |
137 | ||
138 | /* End of lf_sqlperform.c */ |