]>
Commit | Line | Data |
---|---|---|
229843d7 JB |
1 | diff -ruN sendmail-8.14.3/cf/feature/pg_accessdb.m4 sendmail-8.14.3.pgsql/cf/feature/pg_accessdb.m4 |
2 | --- sendmail-8.14.3/cf/feature/pg_accessdb.m4 1969-12-31 16:00:00.000000000 -0800 | |
3 | +++ sendmail-8.14.3.pgsql/cf/feature/pg_accessdb.m4 2007-03-26 13:19:46.000000000 -0700 | |
4 | @@ -0,0 +1,19 @@ | |
5 | +divert(-1) | |
6 | +# By using this file, you agree to be cool and share your knowledge | |
7 | +# | |
8 | +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php | |
9 | +# | |
10 | + | |
11 | +divert(0) | |
12 | +VERSIONID(`$Id: pg_accessdb.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $') | |
13 | +divert(-1) | |
14 | + | |
15 | +define(`_ACCESS_TABLE_', `') | |
16 | +define(`_PG_ACCESS_TABLE_', `') | |
17 | +define(`_TAG_DELIM_', `:')dnl should be in OperatorChars | |
18 | + | |
19 | +LOCAL_CONFIG | |
20 | +# PostgreSQL based access list | |
21 | +Kaccess ifelse(defn(`_ARG_'), `', | |
22 | + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`access', | |
23 | + `_ARG_') | |
24 | diff -ruN sendmail-8.14.3/cf/feature/pg_aliases.m4 sendmail-8.14.3.pgsql/cf/feature/pg_aliases.m4 | |
25 | --- sendmail-8.14.3/cf/feature/pg_aliases.m4 1969-12-31 16:00:00.000000000 -0800 | |
26 | +++ sendmail-8.14.3.pgsql/cf/feature/pg_aliases.m4 2007-03-26 13:19:46.000000000 -0700 | |
27 | @@ -0,0 +1,19 @@ | |
28 | +divert(-1) | |
29 | +# By using this file, you agree to be cool and share your knowledge | |
30 | +# | |
31 | +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php | |
32 | +# | |
33 | + | |
34 | +divert(0) | |
35 | +VERSIONID(`$Id: pg_aliases.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $') | |
36 | +divert(-1) | |
37 | + | |
38 | +undefine(`ALIAS_FILE') | |
39 | +define(`_ALIASES_TABLE_', `') | |
40 | +define(`_PG_ALIASES_TABLE_', `') | |
41 | + | |
42 | +LOCAL_CONFIG | |
43 | +# PostgreSQL based local aliases | |
44 | +Kaliases ifelse(defn(`_ARG_'), `', | |
45 | + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`aliases', | |
46 | + `_ARG_') | |
47 | diff -ruN sendmail-8.14.3/cf/feature/pg_domaintable.m4 sendmail-8.14.3.pgsql/cf/feature/pg_domaintable.m4 | |
48 | --- sendmail-8.14.3/cf/feature/pg_domaintable.m4 1969-12-31 16:00:00.000000000 -0800 | |
49 | +++ sendmail-8.14.3.pgsql/cf/feature/pg_domaintable.m4 2007-03-26 13:19:46.000000000 -0700 | |
50 | @@ -0,0 +1,18 @@ | |
51 | +divert(-1) | |
52 | +# By using this file, you agree to be cool and share your knowledge | |
53 | +# | |
54 | +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php | |
55 | +# | |
56 | + | |
57 | +divert(0) | |
58 | +VERSIONID(`$Id: pg_domaintable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $') | |
59 | +divert(-1) | |
60 | + | |
61 | +define(`_DOMAIN_TABLE_', `') | |
62 | +define(`_PG_DOMAIN_TABLE', `') | |
63 | + | |
64 | +LOCAL_CONFIG | |
65 | +# PostgreSQL based domain rewriting table | |
66 | +Kdomaintable ifelse(defn(`_ARG_'), `', | |
67 | + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`domaintable', | |
68 | + `_ARG_') | |
69 | diff -ruN sendmail-8.14.3/cf/feature/pg_generics.m4 sendmail-8.14.3.pgsql/cf/feature/pg_generics.m4 | |
70 | --- sendmail-8.14.3/cf/feature/pg_generics.m4 1969-12-31 16:00:00.000000000 -0800 | |
71 | +++ sendmail-8.14.3.pgsql/cf/feature/pg_generics.m4 2007-03-26 13:19:46.000000000 -0700 | |
72 | @@ -0,0 +1,18 @@ | |
73 | +divert(-1) | |
74 | +# By using this file, you agree to be cool and share your knowledge | |
75 | +# | |
76 | +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php | |
77 | +# | |
78 | + | |
79 | +divert(0) | |
80 | +VERSIONID(`$Id: pg_genericstable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $') | |
81 | +divert(-1) | |
82 | + | |
83 | +define(`_GENERICS_TABLE_', `') | |
84 | +define(`_PG_GENERICS_TABLE', `') | |
85 | + | |
86 | +LOCAL_CONFIG | |
87 | +# PostgreSQL based generic domain mapping table, similar to userdb | |
88 | +Kgenerics ifelse(defn(`_ARG_'), `', | |
89 | + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`generics', | |
90 | + `_ARG_') | |
91 | diff -ruN sendmail-8.14.3/cf/feature/pg_mailer.m4 sendmail-8.14.3.pgsql/cf/feature/pg_mailer.m4 | |
92 | --- sendmail-8.14.3/cf/feature/pg_mailer.m4 1969-12-31 16:00:00.000000000 -0800 | |
93 | +++ sendmail-8.14.3.pgsql/cf/feature/pg_mailer.m4 2007-03-26 13:19:46.000000000 -0700 | |
94 | @@ -0,0 +1,18 @@ | |
95 | +divert(-1) | |
96 | +# By using this file, you agree to be cool and share your knowledge | |
97 | +# | |
98 | +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php | |
99 | +# | |
100 | + | |
101 | +divert(0) | |
102 | +VERSIONID(`$Id: pg_mailertable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $') | |
103 | +divert(-1) | |
104 | + | |
105 | +define(`_MAILER_TABLE_', `') | |
106 | +define(`_PG_MAILER_TABLE', `') | |
107 | + | |
108 | +LOCAL_CONFIG | |
109 | +# PostgreSQL based mailer table, for overriding domain and MX | |
110 | +Kmailertable ifelse(defn(`_ARG_'), `', | |
111 | + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`mailertable', | |
112 | + `_ARG_') | |
113 | diff -ruN sendmail-8.14.3/cf/feature/pg_usersdb.m4 sendmail-8.14.3.pgsql/cf/feature/pg_usersdb.m4 | |
114 | --- sendmail-8.14.3/cf/feature/pg_usersdb.m4 1969-12-31 16:00:00.000000000 -0800 | |
115 | +++ sendmail-8.14.3.pgsql/cf/feature/pg_usersdb.m4 2007-03-26 13:19:46.000000000 -0700 | |
116 | @@ -0,0 +1,18 @@ | |
117 | +divert(-1) | |
118 | +# By using this file, you agree to be cool and share your knowledge | |
119 | +# | |
120 | +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php | |
121 | +# | |
122 | + | |
123 | +divert(0) | |
124 | +VERSIONID(`$Id: pg_usersdb.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $') | |
125 | +divert(-1) | |
126 | + | |
127 | +define(`_REWRITE_TABLE_', `') | |
128 | +define(`_PG_REWRITE_TABLE_', `') | |
129 | + | |
130 | +LOCAL_CONFIG | |
131 | +# PostgreSQL based user rewrite table (can turn "John.Doe" into "jdoe") | |
132 | +Kusersdb ifelse(defn(`_ARG_'), `', | |
133 | + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`usersdb', | |
134 | + `_ARG_') | |
135 | diff -ruN sendmail-8.14.3/cf/feature/pg_virtualusers.m4 sendmail-8.14.3.pgsql/cf/feature/pg_virtualusers.m4 | |
136 | --- sendmail-8.14.3/cf/feature/pg_virtualusers.m4 1969-12-31 16:00:00.000000000 -0800 | |
137 | +++ sendmail-8.14.3.pgsql/cf/feature/pg_virtualusers.m4 2007-03-26 13:19:46.000000000 -0700 | |
138 | @@ -0,0 +1,18 @@ | |
139 | +divert(-1) | |
140 | +# By using this file, you agree to be cool and share your knowledge | |
141 | +# | |
142 | +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php | |
143 | +# | |
144 | + | |
145 | +divert(0) | |
146 | +VERSIONID(`$Id: pg_virtusertable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $') | |
147 | +divert(-1) | |
148 | + | |
149 | +define(`_VIRTUSER_TABLE_', `') | |
150 | +define(`_PG_VIRTUSER_TABLE_', `') | |
151 | + | |
152 | +LOCAL_CONFIG | |
153 | +# PostgreSQL based virtual user table (maps incoming users) | |
154 | +Kvirtuser ifelse(defn(`_ARG_'), `', | |
155 | + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`virtusertable', | |
156 | + `_ARG_') | |
157 | diff -ruN sendmail-8.14.3/pgsql-build.mc sendmail-8.14.3.pgsql/pgsql-build.mc | |
158 | --- sendmail-8.14.3/pgsql-build.mc 1969-12-31 16:00:00.000000000 -0800 | |
159 | +++ sendmail-8.14.3.pgsql/pgsql-build.mc 2007-03-26 13:19:46.000000000 -0700 | |
160 | @@ -0,0 +1,32 @@ | |
161 | +###################################################################### | |
162 | +# This is the Blue Labs m4 file for the Sendmail w/ Postgres Tables patch. | |
163 | +# | |
164 | +# The website for building sendmail with this patch is at | |
165 | +# http://blue-labs.org/software/sm-pgsql/sendmail.php | |
166 | +# | |
167 | +# This patch may eventually be available to Gentoo (http://gentoo.org/) | |
168 | +# users with the "USE=postgres" use flag | |
169 | +# | |
170 | +# !!! EDIT THE CONFIGURATION SETTINGS TO MATCH YOUR NEEDS !!! | |
171 | +# | |
172 | +# NOTE: This is a specialised .cf for the postgresql patch only | |
173 | +# | |
174 | +VERSIONID(`(#) Blue Labs bluelabs.mc v 11.1 (Blue Labs) 12 Jan 2007') | |
175 | +###################################################################### | |
176 | + | |
177 | +## | |
178 | +# See http://blue-labs.org/software/sm-pgsql/sendmail.php for detailed | |
179 | +# instructions | |
180 | +# | |
181 | +# TODO: replace 'newaliases' and 'makemap' targets with "don't run this" | |
182 | +# update man pages also | |
183 | +## | |
184 | + | |
185 | +# uncomment these two lines if you use /usr/local/pgsql | |
186 | +# APPENDDEF(`confINCDIRS',`-I/usr/local/pgsql/include')dnl | |
187 | +# APPENDDEF(`confLIBDIRS',`-L/usr/local/pgsql/lib')dnl | |
188 | + | |
189 | +APPENDDEF(`confLIBS',`-lpq')dnl | |
190 | +APPENDDEF(`confMAPDEF',`-DPGSQLMAP')dnl | |
191 | +APPENDDEF(`DATABASE_MAP_TYPE', `pgsql')dnl | |
192 | + | |
193 | diff -ruN sendmail-8.14.3/pgsql-config.mc sendmail-8.14.3.pgsql/pgsql-config.mc | |
194 | --- sendmail-8.14.3/pgsql-config.mc 1969-12-31 16:00:00.000000000 -0800 | |
195 | +++ sendmail-8.14.3.pgsql/pgsql-config.mc 2007-03-26 13:19:46.000000000 -0700 | |
196 | @@ -0,0 +1,51 @@ | |
197 | +###################################################################### | |
198 | +# This is the Blue Labs m4 file for the Sendmail w/ Postgres Tables patch. | |
199 | +# | |
200 | +# The website for building sendmail with this patch is at | |
201 | +# http://blue-labs.org/software/sm-pgsql/sendmail.php | |
202 | +# | |
203 | +# This patch may eventually be available to Gentoo (http://gentoo.org/) | |
204 | +# users with the "USE=postgres" use flag | |
205 | +# | |
206 | +# !!! EDIT THE CONFIGURATION SETTINGS TO MATCH YOUR NEEDS !!! | |
207 | +# | |
208 | +# NOTE: This is a specialised .cf for the postgresql patch only | |
209 | +# | |
210 | +VERSIONID(`(#) Blue Labs bluelabs.mc v 12.0 (Blue Labs) 12 Dec 2007') | |
211 | +###################################################################### | |
212 | + | |
213 | +## | |
214 | +# See http://blue-labs.org/software/sm-pgsql/sendmail.php for detailed | |
215 | +# instructions | |
216 | +## | |
217 | + | |
218 | +dnl ## | |
219 | +dnl # example line: | |
220 | +dnl # pgsql [-h <pgsql server>] -c <connection string> -s <query string> | |
221 | +dnl ## | |
222 | + | |
223 | +# | |
224 | +# PgSql | |
225 | +# | |
226 | +# add the flag -f to force case sensitive queries, by default both the | |
227 | +# search and the value will be folded to lower case. by default %s will be | |
228 | +# rewritten to by lower('%s'). if -f is specified, then it will only be | |
229 | +# written as ('%s') and both the input value and the row value MUST match | |
230 | +# case exactly. | |
231 | +# | |
232 | + | |
233 | +define(`PG_CONNSTR', "host=localhost dbname=sendmail user=sendmail password=raisins") | |
234 | +define(`SELECT', "select distinct s_out from ) | |
235 | +define(`WHERE', where ``lower'' (s_in) = %s") | |
236 | +FEATURE(`pg_aliases', pgsql -c `PG_CONNSTR' -s `SELECT' `aliases' `WHERE')dnl | |
237 | +FEATURE(`pg_virtualusers', pgsql -c `PG_CONNSTR' -s `SELECT' `virtualusers' `WHERE')dnl | |
238 | +FEATURE(`pg_usersdb', pgsql -c `PG_CONNSTR' -s `SELECT' `userrewrite' `WHERE')dnl | |
239 | +FEATURE(`pg_accessdb', pgsql -c `PG_CONNSTR' -s `SELECT' `access' `WHERE')dnl | |
240 | +FEATURE(`pg_domaintable', pgsql -c `PG_CONNSTR' -s `SELECT' `domaintable' `WHERE')dnl | |
241 | +FEATURE(`pg_generics', pgsql -c `PG_CONNSTR' -s `SELECT' `genericstable' `WHERE')dnl | |
242 | +FEATURE(`pg_mailer', pgsql -c `PG_CONNSTR' -s `SELECT' `mailertable' `WHERE')dnl | |
243 | + | |
244 | +define(`confPROCESS_TITLE_PREFIX', `[Blue-PgSQL]')dnl | |
245 | +define(`confSMTP_LOGIN_MSG', `Mail server\ | |
246 | + \ | |
247 | + Unauthorized use prohibited\ | |
248 | + \ | |
249 | + Spam is prohibited here and any detected spam may be used in prosecution\ | |
250 | + against the spammer. This setup uses PgSQL (postgresql) for most of it''`s\ | |
251 | + tables, for information on this, see\ | |
252 | + http://blue-labs.org/software/sm-pgsql/sendmail.php\ | |
253 | + Don''`t bitch if your MTA is busted and doesn''`t play well with others.\ | |
254 | + \ | |
255 | +')dnl | |
256 | + | |
257 | +dnl # Don't attempt to rebuild an aliases file, sm-pgsql doesn't use files | |
258 | +dnl # however if you have multiple alias tables and DO use files, remove this | |
259 | +dnl # next line | |
260 | +define(`confALIAS_WAIT', `0')dnl | |
261 | diff -ruN sendmail-8.14.3/sendmail/README sendmail-8.14.3.pgsql/sendmail/README | |
262 | --- sendmail-8.14.3/sendmail/README 2006-11-13 14:27:27.000000000 -0800 | |
263 | +++ sendmail-8.14.3.pgsql/sendmail/README 2007-03-26 13:19:46.000000000 -0700 | |
264 | @@ -119,6 +119,11 @@ | |
265 | have to install the UMich or OpenLDAP | |
266 | (http://www.openldap.org/) ldap and lber libraries to use | |
267 | this flag. | |
268 | +PGSQLMAP PostgreSQL SQL query support. You will need to have | |
269 | + PostgreSQL include files and libraries installed to use this | |
270 | + feature. Information on PostgreSQL can be found at | |
271 | + http://www.postgresql.org/ Support for this map may be | |
272 | + found at http://blue-labs.org/software/sm-pgsql/sendmail.php | |
273 | MAP_REGEX Regular Expression support. You will need to use an | |
274 | operating system which comes with the POSIX regex() | |
275 | routines or install a regexp library such as libregex from | |
276 | --- sendmail-8.16.1/sendmail/conf.c.orig 2020-06-04 08:27:49.000000000 +0200 | |
277 | +++ sendmail-8.16.1/sendmail/conf.c 2020-08-29 10:15:17.896341069 +0200 | |
278 | @@ -576,6 +576,12 @@ | |
279 | ldapmap_lookup, null_map_store); | |
280 | #endif | |
281 | ||
282 | +#ifdef PGSQLMAP | |
283 | + MAPDEF("pgsql", NULL, MCF_ALIASOK|MCF_NOTPERSIST, | |
284 | + pgsql_map_parseargs, pgsql_map_open, pgsql_map_close, | |
285 | + pgsql_map_lookup, null_map_store); | |
286 | +#endif | |
287 | + | |
288 | #if PH_MAP | |
289 | MAPDEF("ph", NULL, MCF_NOTPERSIST, | |
290 | ph_map_parseargs, ph_map_open, ph_map_close, | |
291 | @@ -5864,6 +5870,9 @@ | |
292 | #if LDAP_REFERRALS | |
293 | "LDAP_REFERRALS", | |
294 | #endif | |
295 | +#if PGSQLMAP | |
296 | + "PGSQLMAP", | |
297 | +#endif /* PGSQLMAP */ | |
298 | #if LOG | |
299 | "LOG", | |
300 | #endif | |
301 | --- sendmail-8.14.3/sendmail/map.c 2007-10-09 20:06:45.000000000 -0400 | |
302 | +++ sendmail-8.14.3.pgsql/sendmail/map.c 2009-11-09 19:54:47.214965897 -0500 | |
303 | @@ -4706,6 +4706,588 @@ | |
304 | } | |
305 | } | |
306 | #endif /* LDAPMAP */ | |
307 | + | |
308 | +#ifdef PGSQLMAP | |
309 | +#include <libpq-fe.h> | |
310 | + | |
311 | +/* | |
312 | + * PostgreSQL map functionality for Sendmail 8.14.3 | |
313 | + * Portions Copyright (C) 2000 Jonathan Yarden <jyarden@bluegrass.net> | |
314 | + * Remainder copyright (c) 2000-2009 David Ford <david@blue-labs.org> | |
315 | + * | |
316 | + * For information on PostgreSQL, visit http://www.pgsql.com/ | |
317 | + * Information on this patch and setup is at | |
318 | + * http://blue-labs.org/software/sm-pgsql/sendmail.php | |
319 | + * | |
320 | + * This patch, because it integrates with and is based on the existing | |
321 | + * prior work of Sendmail, is considered by me to be a "derivative | |
322 | + * work" subject to the Sendmail licensing terms. Sendmail, Inc. in not | |
323 | + * responsible for this code. | |
324 | + * | |
325 | + * USE AT YOUR OWN RISK. NO WARRANTY OF ANY KIND IS PROVIDED. PLEASE | |
326 | + * READ THE INSTRUCTIONS FOR USE OF THIS PATCH BEFORE CONTACTING THE | |
327 | + * AUTHOR OR SENDMAIL, INC. NO SUPPORT OF ANY KIND WILL BE PROVIDED | |
328 | + * BY SENDMAIL, INC. FOR THIS PATCH. | |
329 | + */ | |
330 | + | |
331 | +/* | |
332 | +struct pgsqlmap | |
333 | +{ | |
334 | + struct pgsqlmap *p,*n; | |
335 | + char *connstr; | |
336 | + PGconn *conn; | |
337 | + pid_t opener_pid; | |
338 | + char *mapname; | |
339 | +} *pgsqlmap = NULL; */ | |
340 | + | |
341 | +char *pgsql_skip_quotes(char *p) | |
342 | +{ | |
343 | + p = strchr(p,'"'); | |
344 | + if (p) | |
345 | + { | |
346 | + p++; | |
347 | + p = strchr(p,'"'); | |
348 | + if (p) p++; | |
349 | + } | |
350 | + return p; | |
351 | +} | |
352 | + | |
353 | +/* | |
354 | + * Parse PostgreSQL map definition args. | |
355 | + * | |
356 | + * Nothing really special here, since to be perfectly honest, I have never | |
357 | + * seen or used almost all of these options. Most of this code was taken | |
358 | + * directly from existing Sendmail source code. | |
359 | + */ | |
360 | +bool pgsql_map_parseargs(MAP *map, char *args) | |
361 | +{ | |
362 | + register char *p = args; | |
363 | + register int done; | |
364 | + | |
365 | + map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL; | |
366 | + for (;;) | |
367 | + { | |
368 | + while (isascii(*p) && isspace(*p)) | |
369 | + p++; | |
370 | + if (*p != '-') | |
371 | + break; | |
372 | + switch (*++p) | |
373 | + { | |
374 | + case 'A': | |
375 | + map->map_mflags |= MF_APPEND; | |
376 | + break; | |
377 | + | |
378 | + case 'N': | |
379 | + map->map_mflags |= MF_INCLNULL; | |
380 | + map->map_mflags &= ~MF_TRY0NULL; | |
381 | + break; | |
382 | + | |
383 | + case 'O': | |
384 | + map->map_mflags &= ~MF_TRY1NULL; | |
385 | + break; | |
386 | + | |
387 | + case 'T': | |
388 | + map->map_tapp = ++p; | |
389 | + break; | |
390 | + | |
391 | + case 'a': | |
392 | + map->map_app = ++p; | |
393 | + break; | |
394 | + | |
395 | + case 'f': | |
396 | + map->map_mflags |= MF_NOFOLDCASE; | |
397 | + break; | |
398 | + | |
399 | + case 'h': | |
400 | + map->map_db2 = ++p; | |
401 | + break; | |
402 | + | |
403 | + case 'm': | |
404 | + map->map_mflags |= MF_MATCHONLY; | |
405 | + break; | |
406 | + | |
407 | + case 'o': | |
408 | + map->map_mflags |= MF_OPTIONAL; | |
409 | + break; | |
410 | + | |
411 | + case 'q': | |
412 | + map->map_mflags |= MF_KEEPQUOTES; | |
413 | + break; | |
414 | + | |
415 | + case 't': | |
416 | + map->map_mflags |= MF_NODEFER; | |
417 | + break; | |
418 | + | |
419 | +/* | |
420 | + * Start of PostgreSQL specific args. I cheat and use some existing | |
421 | + * Sendmail variables here since this map class makes no other use of them. | |
422 | + */ | |
423 | + | |
424 | + case 'c': /* connection string */ | |
425 | + map->map_keycolnm = ++p; | |
426 | + p = pgsql_skip_quotes(p); | |
427 | + break; | |
428 | + | |
429 | + case 's': /* select statement */ | |
430 | + map->map_valcolnm = ++p; | |
431 | + p = pgsql_skip_quotes(p); | |
432 | + break; | |
433 | + } | |
434 | + | |
435 | + if (*p != '\0') | |
436 | + *p++ = '\0'; | |
437 | + } | |
438 | + | |
439 | + if (map->map_app != NULL) | |
440 | + map->map_app = newstr(map->map_app); | |
441 | + | |
442 | + if (map->map_tapp != NULL) | |
443 | + map->map_tapp = newstr(map->map_tapp); | |
444 | + | |
445 | + if (map->map_keycolnm != NULL) { /* database connect string */ | |
446 | + map->map_keycolnm = newstr(map->map_keycolnm); | |
447 | + stripquotes(map->map_keycolnm); | |
448 | + p = map->map_keycolnm; | |
449 | + while(*p==' ') | |
450 | + p++; | |
451 | + map->map_keycolnm = p; | |
452 | + } else { | |
453 | + sm_syslog(LOG_WARNING, CurEnv->e_id, "No PostgreSQL connect string for %s map %s", | |
454 | + map->map_class->map_cname, map->map_mname); | |
455 | + syserr("451 4.3.5 No PostgreSQL connect string for map %s", | |
456 | + map->map_mname); | |
457 | + SM_SET_H_ERRNO(TRY_AGAIN); | |
458 | + errno = DB_NOTFOUND; | |
459 | + return false; | |
460 | + } | |
461 | + | |
462 | + if (map->map_valcolnm != NULL) { /* select statement */ | |
463 | + map->map_valcolnm = newstr(map->map_valcolnm); | |
464 | + stripquotes(map->map_valcolnm); | |
465 | + p = map->map_valcolnm; | |
466 | + while(*p==' ') | |
467 | + p++; | |
468 | + map->map_valcolnm = p; | |
469 | + } else { | |
470 | + sm_syslog(LOG_WARNING, CurEnv->e_id, "No PostgreSQL select statement for %s map %s", | |
471 | + map->map_class->map_cname, map->map_mname); | |
472 | + syserr("451 5.3.5 No PostgreSQL select statement for map %s", | |
473 | + map->map_mname); | |
474 | + SM_SET_H_ERRNO(TRY_AGAIN); | |
475 | + errno = DB_NOTFOUND; | |
476 | + return false; | |
477 | + } | |
478 | + | |
479 | + return true; | |
480 | +} | |
481 | + | |
482 | +#if 0 | |
483 | +/* | |
484 | + * search our list of map connections for a entry that matches our | |
485 | + * connection. it should have the same host and connection string, as well | |
486 | + * as the same PID. someone can choose to put their maps on different | |
487 | + * databases, so we cannot share a connection. | |
488 | + */ | |
489 | + | |
490 | +PGconn *pgsql_getconn(char *connstr, char *mapname) | |
491 | +{ | |
492 | + pid_t p = getpid(); | |
493 | + | |
494 | + // if no map has been allocated, return immediately | |
495 | + if(!pgsqlmap) return NULL; | |
496 | + | |
497 | + // rewind | |
498 | + while(pgsqlmap->p) pgsqlmap = pgsqlmap->p; | |
499 | + | |
500 | + #ifdef PGSQLDEBUG | |
501 | + sm_syslog(LOG_INFO, CurEnv->e_id, "pgsql_getconn (connection string:%s, pid:%i)", connstr, p); | |
502 | + #endif | |
503 | + | |
504 | + // only return connections that match everything | |
505 | + do | |
506 | + { | |
507 | + if(pgsqlmap->conn) | |
508 | + if (!strncmp(connstr, pgsqlmap->connstr, strlen(connstr)+1)) | |
509 | + if (pgsqlmap->opener_pid == p) | |
510 | + if (!strncmp(pgsqlmap->mapname, mapname, strlen(mapname)) | |
511 | + return pgsqlmap->conn; | |
512 | + | |
513 | + // if there is more than one map and we're still searching, bump to the next one | |
514 | + if (pgsqlmap->n) | |
515 | + pgsqlmap = pgsqlmap->n; | |
516 | + else | |
517 | + break; | |
518 | + } while(1); | |
519 | + | |
520 | + return NULL; | |
521 | +} | |
522 | + | |
523 | +/* | |
524 | + * add a new map entry structure and populate it | |
525 | + */ | |
526 | +void pgsql_addconn(char *host, char *connstr, PGconn *conn, mapname) | |
527 | +{ | |
528 | + int count=1; | |
529 | + | |
530 | + if (!pgsqlmap) | |
531 | + // create a brand new map structure | |
532 | + pgsqlmap= (struct pgsqlmap *) xalloc(sizeof(struct pgsqlmap)); | |
533 | + | |
534 | + else | |
535 | + { | |
536 | + // fast-forward to the end of the list | |
537 | + while(pgsqlmap->n) | |
538 | + { | |
539 | + count++; | |
540 | + pgsqlmap = pgsqlmap->n; | |
541 | + } | |
542 | + | |
543 | + pgsqlmap->n = (struct pgsqlmap *) xalloc(sizeof(struct pgsqlmap)); | |
544 | + pgsqlmap->n->p = pgsqlmap; | |
545 | + pgsqlmap = pgsqlmap->n; | |
546 | + } | |
547 | + | |
548 | + bzero(pgsqlmap, sizeof(struct pgsqlmap)); | |
549 | + pgsqlmap->connstr =connstr; | |
550 | + pgsqlmap->conn =conn; | |
551 | + pgsqlmap->opener_pid =getpid(); | |
552 | + pgsqlmap->mapname =mapname; | |
553 | + | |
554 | + #ifdef PGSQLDEBUG | |
555 | + sm_syslog(LOG_INFO, CurEnv->e_id, "pgsql_ add map connection (connection string:%s, connptr:%p, pid:%i), maplist size is %i", | |
556 | + pgsqlmap->connstr, pgsqlmap->conn, pgsqlmap->opener_pid, count); | |
557 | + #endif | |
558 | +} | |
559 | + | |
560 | +int psql_removeconn(PGconn *conn, char *mapname) | |
561 | +{ | |
562 | + if(!pgsqlmap) return 0; | |
563 | + | |
564 | + while(pgsqlmap->p) pgsqlmap = pgsqlmap->p; | |
565 | + | |
566 | + do | |
567 | + { | |
568 | + if (pgsqlmap->conn == conn && !strncmp(pgsqlmap->mapname, mapname, strlen(mapname)) | |
569 | + { | |
570 | + // the map data doesn't belong to us, just deallocate the map pointer | |
571 | + struct pgsqlmap *z = pgsqlmap; | |
572 | + | |
573 | + #ifdef PGSQLDEBUG | |
574 | + sm_syslog(LOG_INFO, CurEnv->e_id, "pgsql_ delete map connection (connection string:%s, connptr:%p, pid:%i)", | |
575 | + pgsqlmap->connstr, pgsqlmap->conn, pgsqlmap->opener_pid); | |
576 | + #endif | |
577 | + | |
578 | + if (z->p && z->n) | |
579 | + { | |
580 | + z->p->n = z->n; | |
581 | + z->n->p = z->p; | |
582 | + free(z); | |
583 | + pgsqlmap = pgsqlmap->n; | |
584 | + return 1; | |
585 | + } | |
586 | + | |
587 | + else if (z->p) | |
588 | + { | |
589 | + z->p->n = NULL; | |
590 | + free(z); | |
591 | + pgsqlmap = pgsqlmap->p; | |
592 | + return 1; | |
593 | + } | |
594 | + | |
595 | + else if (z->n) | |
596 | + { | |
597 | + z->n->p = NULL; | |
598 | + free(z); | |
599 | + pgsqlmap = pgsqlmap->n; | |
600 | + return 1; | |
601 | + } | |
602 | + | |
603 | + // only return 1 if no map references are left so the pgsql connection can be shut down | |
604 | + else | |
605 | + { | |
606 | + free(z); | |
607 | + pgsqlmap = NULL; | |
608 | + return 1; | |
609 | + } | |
610 | + | |
611 | + } | |
612 | + | |
613 | + if (pgsqlmap->n) | |
614 | + pgsqlmap = pgsqlmap->n; | |
615 | + else | |
616 | + break; | |
617 | + } while(1); | |
618 | + | |
619 | + // no maps found | |
620 | + return 0; | |
621 | +} | |
622 | +#endif | |
623 | + | |
624 | +/* | |
625 | + * Open a PostgreSQL database connection using the connection string, the | |
626 | + * mode parameter is entirely ignored - it has no purpose in SQL. | |
627 | + * | |
628 | + * Returns TRUE if the database was opened or FALSE if it choked | |
629 | + */ | |
630 | +bool pgsql_map_open(MAP *map, int mode) | |
631 | +{ | |
632 | + char *s= NULL; | |
633 | + int n, retries; | |
634 | + | |
635 | + /* | |
636 | + * each map can have a different connection, so we can't easily share | |
637 | + * it. further, each connection is protected between thread instances. | |
638 | + */ | |
639 | + | |
640 | + /* | |
641 | + * this is the most likely test so it comes first. we have a connection | |
642 | + * to the server, if the status appears good, return. note: the status | |
643 | + * may be misleading, the server may have crashed underneath us or | |
644 | + * terminated our connection for any of several reasons. we won't know | |
645 | + * that until we actually use it however. | |
646 | + */ | |
647 | + if (map->map_db1 && PQstatus(map->map_db1) == CONNECTION_OK) | |
648 | + { | |
649 | + // the connection is shared between all maps, we don't need to differentiate | |
650 | + #ifdef PGSQLDEBUG | |
651 | + sm_syslog(LOG_INFO, CurEnv->e_id, "Connection is good (connection string:%s, connptr:%p)", | |
652 | + map->map_keycolnm, map->map_db1); | |
653 | + #endif | |
654 | + | |
655 | + return true; | |
656 | + } | |
657 | + | |
658 | + #ifdef PGSQLDEBUG | |
659 | + if (!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD) | |
660 | + sm_syslog(LOG_INFO, CurEnv->e_id, "Connection to SQL server not found or stale for map:%s, looking for a new one", map->map_mname); | |
661 | + #endif | |
662 | + | |
663 | + retries=10; | |
664 | + while ((!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD) && retries-- >0) | |
665 | + { | |
666 | + /* | |
667 | + * now either conn is still null (not yet allocated), or our connection | |
668 | + * is bad. synchronous connections only have _OK or _BAD. looks like | |
669 | + * we have to reset or make a new connection. allocate space and try to | |
670 | + * connect | |
671 | + */ | |
672 | + if (!map->map_db1) | |
673 | + { | |
674 | + map->map_db1 = PQconnectdb(map->map_keycolnm); | |
675 | + PQsetErrorVerbosity(map->map_db1, PQERRORS_VERBOSE); | |
676 | + //pgsql_addconn(map->map_keycolnm, map->map_db1, map->map_mname); | |
677 | + map->map_pid = getpid(); /* save PID for check on close */ | |
678 | + } | |
679 | + | |
680 | + else | |
681 | + PQreset(map->map_db1); | |
682 | + | |
683 | + if (!map->map_db1) | |
684 | + { | |
685 | + sm_syslog(LOG_WARNING, CurEnv->e_id, "Cannot open %s map %s using %s, attempt %i", | |
686 | + map->map_class->map_cname, map->map_mname, map->map_keycolnm, 10-retries); | |
687 | + } | |
688 | + | |
689 | + if (PQstatus(map->map_db1) == CONNECTION_BAD) | |
690 | + { | |
691 | + sm_syslog(LOG_WARNING, CurEnv->e_id, "Cannot open %s map %s using %s (%s), attempt %i", | |
692 | + map->map_class->map_cname, map->map_mname, map->map_keycolnm, | |
693 | + PQerrorMessage(map->map_db1), 10-retries); | |
694 | + } | |
695 | + } | |
696 | + | |
697 | + if (!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD) | |
698 | + { | |
699 | + syserr("451 4.3.5 Map database unreachable"); | |
700 | + if (map->map_db1) | |
701 | + { | |
702 | + //psql_removeconn(conn, map->map_mname); | |
703 | + PQfinish(map->map_db1); | |
704 | + map->map_db1 = NULL; | |
705 | + } | |
706 | + | |
707 | + errno = DB_NOTFOUND; | |
708 | + SM_SET_H_ERRNO(TRY_AGAIN); | |
709 | + | |
710 | + return false; | |
711 | + } | |
712 | + | |
713 | + return true; | |
714 | +} | |
715 | + | |
716 | +/* | |
717 | + * Close the PostgreSQL database connection, check that the opening process | |
718 | + * is the closing process; ignore if not. | |
719 | + */ | |
720 | +void pgsql_map_close(MAP *map) | |
721 | +{ | |
722 | + int r; | |
723 | + | |
724 | + if (map->map_pid == getpid()) | |
725 | + { | |
726 | + //conn = map->map_db1; | |
727 | +/* | |
728 | + r = psql_removeconn(conn, map->map_mname); | |
729 | + if(r) | |
730 | + { | |
731 | +*/ PQfinish(map->map_db1); | |
732 | + map->map_db1 = NULL; | |
733 | + #ifdef PGSQLDEBUG | |
734 | + sm_syslog(LOG_INFO, CurEnv->e_id, "Closed connection for map %s", map->map_mname); | |
735 | + #endif | |
736 | +/* } | |
737 | + | |
738 | + #ifdef PGSQLDEBUG | |
739 | + else | |
740 | + sm_syslog(LOG_INFO, CurEnv->e_id, "No connection found for map: %s", map->map_mname); | |
741 | + #endif | |
742 | +*/ } | |
743 | +} | |
744 | + | |
745 | +/* | |
746 | +** PGSQL_MAP_LOOKUP -- look up a datum in a PGSQL map | |
747 | +** | |
748 | +** Attempt to map an incoming key value with a PostgreSQL query. | |
749 | +** | |
750 | +** This performs the query specified in the Sendmail config file and | |
751 | +** uses the value of the first row and column as the map data value. | |
752 | +** All other rows and columns are ignored. | |
753 | +*/ | |
754 | +char * | |
755 | +pgsql_map_lookup(MAP *map, char *name, char **av, int *statp) | |
756 | +{ | |
757 | + int len,esc_len,ntuples,r,retries; | |
758 | + char *format,*workingbuf,*trustedbuf; | |
759 | + char sname[MAXNAME+1]; | |
760 | + char resbuf[MAXNAME+1]; | |
761 | + PGresult *res; | |
762 | + | |
763 | + /* | |
764 | + * Check the backend to make sure it's still valid. If it's not, try and | |
765 | + * reset the connection. | |
766 | + */ | |
767 | + if (!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD) | |
768 | + { | |
769 | + #ifdef PGSQLDEBUG | |
770 | + sm_syslog(LOG_INFO, NOQID, "Connection bad for map: %s, reconnecting to SQL server using: %s", map->map_mname, map->map_keycolnm); | |
771 | + #endif | |
772 | + if (!pgsql_map_open(map, 0)) | |
773 | + { | |
774 | + #ifdef PGSQLDEBUG | |
775 | + sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> aborting map lookup"); | |
776 | + #endif | |
777 | + return NULL; | |
778 | + } | |
779 | + } | |
780 | + | |
781 | + bzero(sname,sizeof sname); | |
782 | + bzero(resbuf,sizeof resbuf); | |
783 | + | |
784 | + /* Buffer overflow check. */ | |
785 | + len = strlen(name); | |
786 | + if (len > MAXNAME) | |
787 | + len = MAXNAME; | |
788 | + bcopy(name,sname,len); | |
789 | + | |
790 | + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) | |
791 | + { | |
792 | + //#ifdef PGSQLDEBUG | |
793 | + //sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> making querystring value lowercase"); | |
794 | + //#endif | |
795 | + makelower(sname); | |
796 | + } | |
797 | + | |
798 | + /* Allocate query buffer (select statement + key value) */ | |
799 | + len = strlen(map->map_valcolnm); | |
800 | + esc_len = strlen(sname); | |
801 | + workingbuf = xalloc(esc_len*2+1+9); | |
802 | + trustedbuf = xalloc(len+(esc_len*2)+1+9); | |
803 | + bzero(trustedbuf,len); | |
804 | + | |
805 | + // escape untrusted data passed to us from network | |
806 | + PQescapeStringConn(map->map_db1, trustedbuf, sname, strlen(sname), NULL); | |
807 | + | |
808 | + // if MF_NOFOLDCASE is set, don't wrap this in lower() | |
809 | + if (!bitset(MF_NOFOLDCASE, map->map_mflags)) | |
810 | + format="lower('%s')"; | |
811 | + else | |
812 | + format="'%s'"; | |
813 | + | |
814 | + sprintf(workingbuf, format, trustedbuf); | |
815 | + sprintf(trustedbuf, map->map_valcolnm, workingbuf); | |
816 | + free(workingbuf); | |
817 | + | |
818 | + #ifdef PGSQLDEBUG | |
819 | + sm_syslog(LOG_INFO, CurEnv->e_id, "dbg-sql> %s", trustedbuf); | |
820 | + #endif | |
821 | + | |
822 | + retries = 2; | |
823 | + while (retries--) | |
824 | + { | |
825 | + res = PQexec(map->map_db1, trustedbuf); | |
826 | + if (PQresultStatus(res) == PGRES_TUPLES_OK) | |
827 | + break; | |
828 | + | |
829 | + sm_syslog(LOG_WARNING, CurEnv->e_id, "Cannot query PGSQL database (attempt:%i) \"%s\" using \"%s\" because of: %s", | |
830 | + 10-retries, map->map_keycolnm, trustedbuf, PQresultErrorMessage(res)); | |
831 | + PQclear(res); | |
832 | + | |
833 | + // try to reset connection | |
834 | + if (!pgsql_map_open(map, 0)) | |
835 | + { | |
836 | + #ifdef PGSQLDEBUG | |
837 | + sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> aborting map lookup"); | |
838 | + #endif | |
839 | + return NULL; | |
840 | + } | |
841 | + } | |
842 | + | |
843 | + if (!map->map_db1 || PQresultStatus(res) != PGRES_TUPLES_OK) | |
844 | + { | |
845 | + syserr("451 4.3.1 Cannot query PGSQL database"); | |
846 | + SM_SET_H_ERRNO(TRY_AGAIN); | |
847 | + errno = DB_NOTFOUND; | |
848 | + free(trustedbuf); | |
849 | + return NULL; | |
850 | + } | |
851 | + | |
852 | + /* | |
853 | + * See if anything came back. If no rows were returned, nothing there for | |
854 | + * this query. | |
855 | + */ | |
856 | + ntuples = PQntuples(res); | |
857 | + #ifdef PGSQLDEBUG | |
858 | + sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> finishing map lookup, ntuples:%i", ntuples); | |
859 | + #endif | |
860 | + | |
861 | + if (ntuples <= 0) | |
862 | + { | |
863 | + PQclear(res); | |
864 | + return NULL; | |
865 | + } | |
866 | + | |
867 | + /* | |
868 | + * Get the result from column 0 and clear the rest of the result. | |
869 | + * If the result data is too big, then it's truncated. | |
870 | + */ | |
871 | + len = PQgetlength(res,0,0); | |
872 | + if (len > MAXNAME) | |
873 | + len = MAXNAME; | |
874 | + bcopy(PQgetvalue(res,0,0),resbuf,len); | |
875 | + PQclear(res); | |
876 | + | |
877 | + /* Process results like the other map classes do. */ | |
878 | + | |
879 | + #ifdef PGSQLDEBUG | |
880 | + sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> finishing map lookup, result:\"%s\"", resbuf); | |
881 | + #endif | |
882 | + | |
883 | + if (bitset(MF_MATCHONLY, map->map_mflags)) | |
884 | + return map_rewrite(map, name, strlen(name), NULL); | |
885 | + else | |
886 | + return map_rewrite(map, resbuf, len, av); | |
887 | +} | |
888 | +#endif /* PGSQLMAP */ | |
889 | /* | |
890 | ** PH map | |
891 | */ |