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
6 +# By using this file, you agree to be cool and share your knowledge
8 +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
12 +VERSIONID(`$Id: pg_accessdb.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
15 +define(`_ACCESS_TABLE_', `')
16 +define(`_PG_ACCESS_TABLE_', `')
17 +define(`_TAG_DELIM_', `:')dnl should be in OperatorChars
20 +# PostgreSQL based access list
21 +Kaccess ifelse(defn(`_ARG_'), `',
22 + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`access',
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
29 +# By using this file, you agree to be cool and share your knowledge
31 +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
35 +VERSIONID(`$Id: pg_aliases.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
38 +undefine(`ALIAS_FILE')
39 +define(`_ALIASES_TABLE_', `')
40 +define(`_PG_ALIASES_TABLE_', `')
43 +# PostgreSQL based local aliases
44 +Kaliases ifelse(defn(`_ARG_'), `',
45 + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`aliases',
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
52 +# By using this file, you agree to be cool and share your knowledge
54 +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
58 +VERSIONID(`$Id: pg_domaintable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
61 +define(`_DOMAIN_TABLE_', `')
62 +define(`_PG_DOMAIN_TABLE', `')
65 +# PostgreSQL based domain rewriting table
66 +Kdomaintable ifelse(defn(`_ARG_'), `',
67 + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`domaintable',
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
74 +# By using this file, you agree to be cool and share your knowledge
76 +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
80 +VERSIONID(`$Id: pg_genericstable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
83 +define(`_GENERICS_TABLE_', `')
84 +define(`_PG_GENERICS_TABLE', `')
87 +# PostgreSQL based generic domain mapping table, similar to userdb
88 +Kgenerics ifelse(defn(`_ARG_'), `',
89 + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`generics',
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
96 +# By using this file, you agree to be cool and share your knowledge
98 +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
102 +VERSIONID(`$Id: pg_mailertable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
105 +define(`_MAILER_TABLE_', `')
106 +define(`_PG_MAILER_TABLE', `')
109 +# PostgreSQL based mailer table, for overriding domain and MX
110 +Kmailertable ifelse(defn(`_ARG_'), `',
111 + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`mailertable',
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
118 +# By using this file, you agree to be cool and share your knowledge
120 +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
124 +VERSIONID(`$Id: pg_usersdb.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
127 +define(`_REWRITE_TABLE_', `')
128 +define(`_PG_REWRITE_TABLE_', `')
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',
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
140 +# By using this file, you agree to be cool and share your knowledge
142 +# David, http://blue-labs.org/software/sm-pgsql/sendmail.php
146 +VERSIONID(`$Id: pg_virtusertable.m4,v 2.0 2000/07/19 18:15:16 blu3 Exp $')
149 +define(`_VIRTUSER_TABLE_', `')
150 +define(`_PG_VIRTUSER_TABLE_', `')
153 +# PostgreSQL based virtual user table (maps incoming users)
154 +Kvirtuser ifelse(defn(`_ARG_'), `',
155 + DATABASE_MAP_TYPE MAIL_SETTINGS_DIR`virtusertable',
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
161 +######################################################################
162 +# This is the Blue Labs m4 file for the Sendmail w/ Postgres Tables patch.
164 +# The website for building sendmail with this patch is at
165 +# http://blue-labs.org/software/sm-pgsql/sendmail.php
167 +# This patch may eventually be available to Gentoo (http://gentoo.org/)
168 +# users with the "USE=postgres" use flag
170 +# !!! EDIT THE CONFIGURATION SETTINGS TO MATCH YOUR NEEDS !!!
172 +# NOTE: This is a specialised .cf for the postgresql patch only
174 +VERSIONID(`(#) Blue Labs bluelabs.mc v 11.1 (Blue Labs) 12 Jan 2007')
175 +######################################################################
178 +# See http://blue-labs.org/software/sm-pgsql/sendmail.php for detailed
181 +# TODO: replace 'newaliases' and 'makemap' targets with "don't run this"
182 +# update man pages also
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
189 +APPENDDEF(`confLIBS',`-lpq')dnl
190 +APPENDDEF(`confMAPDEF',`-DPGSQLMAP')dnl
191 +APPENDDEF(`DATABASE_MAP_TYPE', `pgsql')dnl
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
197 +######################################################################
198 +# This is the Blue Labs m4 file for the Sendmail w/ Postgres Tables patch.
200 +# The website for building sendmail with this patch is at
201 +# http://blue-labs.org/software/sm-pgsql/sendmail.php
203 +# This patch may eventually be available to Gentoo (http://gentoo.org/)
204 +# users with the "USE=postgres" use flag
206 +# !!! EDIT THE CONFIGURATION SETTINGS TO MATCH YOUR NEEDS !!!
208 +# NOTE: This is a specialised .cf for the postgresql patch only
210 +VERSIONID(`(#) Blue Labs bluelabs.mc v 12.0 (Blue Labs) 12 Dec 2007')
211 +######################################################################
214 +# See http://blue-labs.org/software/sm-pgsql/sendmail.php for detailed
220 +dnl # pgsql [-h <pgsql server>] -c <connection string> -s <query string>
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
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
244 +define(`confPROCESS_TITLE_PREFIX', `[Blue-PgSQL]')dnl
245 +define(`confSMTP_LOGIN_MSG', `Mail server\
247 + Unauthorized use prohibited\
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.\
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
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
265 have to install the UMich or OpenLDAP
266 (http://www.openldap.org/) ldap and lber libraries to use
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
279 ldapmap_lookup, null_map_store);
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);
289 MAPDEF("ph", NULL, MCF_NOTPERSIST,
290 ph_map_parseargs, ph_map_open, ph_map_close,
291 @@ -5864,6 +5870,9 @@
297 +#endif /* PGSQLMAP */
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 @@
309 +#include <libpq-fe.h>
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>
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
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.
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.
334 + struct pgsqlmap *p,*n;
339 +} *pgsqlmap = NULL; */
341 +char *pgsql_skip_quotes(char *p)
354 + * Parse PostgreSQL map definition args.
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.
360 +bool pgsql_map_parseargs(MAP *map, char *args)
362 + register char *p = args;
365 + map->map_mflags |= MF_TRY0NULL | MF_TRY1NULL;
368 + while (isascii(*p) && isspace(*p))
375 + map->map_mflags |= MF_APPEND;
379 + map->map_mflags |= MF_INCLNULL;
380 + map->map_mflags &= ~MF_TRY0NULL;
384 + map->map_mflags &= ~MF_TRY1NULL;
388 + map->map_tapp = ++p;
392 + map->map_app = ++p;
396 + map->map_mflags |= MF_NOFOLDCASE;
400 + map->map_db2 = ++p;
404 + map->map_mflags |= MF_MATCHONLY;
408 + map->map_mflags |= MF_OPTIONAL;
412 + map->map_mflags |= MF_KEEPQUOTES;
416 + map->map_mflags |= MF_NODEFER;
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.
424 + case 'c': /* connection string */
425 + map->map_keycolnm = ++p;
426 + p = pgsql_skip_quotes(p);
429 + case 's': /* select statement */
430 + map->map_valcolnm = ++p;
431 + p = pgsql_skip_quotes(p);
439 + if (map->map_app != NULL)
440 + map->map_app = newstr(map->map_app);
442 + if (map->map_tapp != NULL)
443 + map->map_tapp = newstr(map->map_tapp);
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;
451 + map->map_keycolnm = p;
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",
457 + SM_SET_H_ERRNO(TRY_AGAIN);
458 + errno = DB_NOTFOUND;
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;
468 + map->map_valcolnm = p;
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",
474 + SM_SET_H_ERRNO(TRY_AGAIN);
475 + errno = DB_NOTFOUND;
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.
490 +PGconn *pgsql_getconn(char *connstr, char *mapname)
492 + pid_t p = getpid();
494 + // if no map has been allocated, return immediately
495 + if(!pgsqlmap) return NULL;
498 + while(pgsqlmap->p) pgsqlmap = pgsqlmap->p;
501 + sm_syslog(LOG_INFO, CurEnv->e_id, "pgsql_getconn (connection string:%s, pid:%i)", connstr, p);
504 + // only return connections that match everything
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;
513 + // if there is more than one map and we're still searching, bump to the next one
515 + pgsqlmap = pgsqlmap->n;
524 + * add a new map entry structure and populate it
526 +void pgsql_addconn(char *host, char *connstr, PGconn *conn, mapname)
531 + // create a brand new map structure
532 + pgsqlmap= (struct pgsqlmap *) xalloc(sizeof(struct pgsqlmap));
536 + // fast-forward to the end of the list
540 + pgsqlmap = pgsqlmap->n;
543 + pgsqlmap->n = (struct pgsqlmap *) xalloc(sizeof(struct pgsqlmap));
544 + pgsqlmap->n->p = pgsqlmap;
545 + pgsqlmap = pgsqlmap->n;
548 + bzero(pgsqlmap, sizeof(struct pgsqlmap));
549 + pgsqlmap->connstr =connstr;
550 + pgsqlmap->conn =conn;
551 + pgsqlmap->opener_pid =getpid();
552 + pgsqlmap->mapname =mapname;
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);
560 +int psql_removeconn(PGconn *conn, char *mapname)
562 + if(!pgsqlmap) return 0;
564 + while(pgsqlmap->p) pgsqlmap = pgsqlmap->p;
568 + if (pgsqlmap->conn == conn && !strncmp(pgsqlmap->mapname, mapname, strlen(mapname))
570 + // the map data doesn't belong to us, just deallocate the map pointer
571 + struct pgsqlmap *z = pgsqlmap;
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);
583 + pgsqlmap = pgsqlmap->n;
591 + pgsqlmap = pgsqlmap->p;
599 + pgsqlmap = pgsqlmap->n;
603 + // only return 1 if no map references are left so the pgsql connection can be shut down
614 + pgsqlmap = pgsqlmap->n;
625 + * Open a PostgreSQL database connection using the connection string, the
626 + * mode parameter is entirely ignored - it has no purpose in SQL.
628 + * Returns TRUE if the database was opened or FALSE if it choked
630 +bool pgsql_map_open(MAP *map, int mode)
636 + * each map can have a different connection, so we can't easily share
637 + * it. further, each connection is protected between thread instances.
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.
647 + if (map->map_db1 && PQstatus(map->map_db1) == CONNECTION_OK)
649 + // the connection is shared between all maps, we don't need to differentiate
651 + sm_syslog(LOG_INFO, CurEnv->e_id, "Connection is good (connection string:%s, connptr:%p)",
652 + map->map_keycolnm, map->map_db1);
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);
664 + while ((!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD) && retries-- >0)
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
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 */
681 + PQreset(map->map_db1);
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);
689 + if (PQstatus(map->map_db1) == CONNECTION_BAD)
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);
697 + if (!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD)
699 + syserr("451 4.3.5 Map database unreachable");
702 + //psql_removeconn(conn, map->map_mname);
703 + PQfinish(map->map_db1);
704 + map->map_db1 = NULL;
707 + errno = DB_NOTFOUND;
708 + SM_SET_H_ERRNO(TRY_AGAIN);
717 + * Close the PostgreSQL database connection, check that the opening process
718 + * is the closing process; ignore if not.
720 +void pgsql_map_close(MAP *map)
724 + if (map->map_pid == getpid())
726 + //conn = map->map_db1;
728 + r = psql_removeconn(conn, map->map_mname);
731 +*/ PQfinish(map->map_db1);
732 + map->map_db1 = NULL;
734 + sm_syslog(LOG_INFO, CurEnv->e_id, "Closed connection for map %s", map->map_mname);
740 + sm_syslog(LOG_INFO, CurEnv->e_id, "No connection found for map: %s", map->map_mname);
746 +** PGSQL_MAP_LOOKUP -- look up a datum in a PGSQL map
748 +** Attempt to map an incoming key value with a PostgreSQL query.
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.
755 +pgsql_map_lookup(MAP *map, char *name, char **av, int *statp)
757 + int len,esc_len,ntuples,r,retries;
758 + char *format,*workingbuf,*trustedbuf;
759 + char sname[MAXNAME+1];
760 + char resbuf[MAXNAME+1];
764 + * Check the backend to make sure it's still valid. If it's not, try and
765 + * reset the connection.
767 + if (!map->map_db1 || PQstatus(map->map_db1) == CONNECTION_BAD)
770 + sm_syslog(LOG_INFO, NOQID, "Connection bad for map: %s, reconnecting to SQL server using: %s", map->map_mname, map->map_keycolnm);
772 + if (!pgsql_map_open(map, 0))
775 + sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> aborting map lookup");
781 + bzero(sname,sizeof sname);
782 + bzero(resbuf,sizeof resbuf);
784 + /* Buffer overflow check. */
785 + len = strlen(name);
788 + bcopy(name,sname,len);
790 + if (!bitset(MF_NOFOLDCASE, map->map_mflags))
792 + //#ifdef PGSQLDEBUG
793 + //sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> making querystring value lowercase");
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);
805 + // escape untrusted data passed to us from network
806 + PQescapeStringConn(map->map_db1, trustedbuf, sname, strlen(sname), NULL);
808 + // if MF_NOFOLDCASE is set, don't wrap this in lower()
809 + if (!bitset(MF_NOFOLDCASE, map->map_mflags))
810 + format="lower('%s')";
814 + sprintf(workingbuf, format, trustedbuf);
815 + sprintf(trustedbuf, map->map_valcolnm, workingbuf);
819 + sm_syslog(LOG_INFO, CurEnv->e_id, "dbg-sql> %s", trustedbuf);
825 + res = PQexec(map->map_db1, trustedbuf);
826 + if (PQresultStatus(res) == PGRES_TUPLES_OK)
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));
833 + // try to reset connection
834 + if (!pgsql_map_open(map, 0))
837 + sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> aborting map lookup");
843 + if (!map->map_db1 || PQresultStatus(res) != PGRES_TUPLES_OK)
845 + syserr("451 4.3.1 Cannot query PGSQL database");
846 + SM_SET_H_ERRNO(TRY_AGAIN);
847 + errno = DB_NOTFOUND;
853 + * See if anything came back. If no rows were returned, nothing there for
856 + ntuples = PQntuples(res);
858 + sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> finishing map lookup, ntuples:%i", ntuples);
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.
871 + len = PQgetlength(res,0,0);
874 + bcopy(PQgetvalue(res,0,0),resbuf,len);
877 + /* Process results like the other map classes do. */
880 + sm_syslog(LOG_INFO, CurEnv->e_id, "dbg> finishing map lookup, result:\"%s\"", resbuf);
883 + if (bitset(MF_MATCHONLY, map->map_mflags))
884 + return map_rewrite(map, name, strlen(name), NULL);
886 + return map_rewrite(map, resbuf, len, av);
888 +#endif /* PGSQLMAP */