Commit | Line | Data |
---|---|---|
420a0d19 CE |
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 */ |