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