]> git.pld-linux.org Git - packages/postfix.git/blame - postfix-pgsql.patch
- removes some compiler warnings during postfix compilation which may cause fatal...
[packages/postfix.git] / postfix-pgsql.patch
CommitLineData
0b72d562 1--- postfix-2.0.16.orig/PGSQL_README 1970-01-01 01:00:00.000000000 +0100
2+++ postfix-2.0.16/PGSQL_README 2003-11-08 20:11:44.000000000 +0100
f512ae96
JB
3@@ -0,0 +1,88 @@
4+[Code contributed by Mathieu Arnold]
5+
6+We've written code to add a pgsql map type. It utilizes the pgsql
7+client library, which can be obtained from:
8+
9+ http://www.postgresql.org/
10+
11+In order to build postfix with pgsql map support, you will need to add
12+-DHAS_PGSQL and -I for the directory containing the postgres headers, and
13+the libpq library (and libcrypt) to AUXLIBS, for example:
14+
15+make -f Makefile.init makefiles \
16+ 'CCARGS=-DHAS_PGSQL -I/some/where/include/postgresql' \
17+ 'AUXLIBS=/some/where/lib/postgres/libpq.a -lcrypt'
18+
19+then, just run 'make'.
20+
21+Postfix installations which may benefit from using pgsql map types
22+include sites that have a need for instantaneous updates of
23+forwarding, and sites that may benefit from having mail exchangers
24+reference a networked database, possibly working in conjunction with a
25+customer database of sorts.
26+
27+Once postfix is built with pgsql support, you can specify a map type
28+in main.cf like this:
29+
30+alias_maps = pgsql:/etc/postfix/pgsql-aliases.cf
31+
32+The file /etc/postfix/pgsql-aliases.cf specifies lots of information
33+telling postfix how to reference the postgresql database. An example
34+postgresql map config file follows:
35+
36+#
37+# postgresql config file for alias lookups on postfix
38+# comments are ok.
39+#
40+
41+# the user name and password to log into the pgsql server
42+user = someone
43+password = some_passwordd
44+
45+# the database name on the servers
46+dbname = customer_database
47+
48+# the table name
49+table = mxaliases
50+
51+#
52+select_field = forw_addr
53+where_field = alias
54+
55+# you may specify additional_conditions here
56+additional_conditions = and status = 'paid'
57+
58+# the above variables will result in a query of
59+# the form:
60+# select forw_addr from mxaliases where alias = '$lookup' and status = 'paid'
61+# ($lookup is escaped so if it contains single quotes or other odd
62+# characters, it will not cause a parse error in the sql).
63+#
64+# the hosts that postfix will try to connect to
65+# and query from (in the order listed)
66+hosts = host1.some.domain host2.some.domain
67+
68+# end postgresql config file
69+
70+Some notes:
71+
72+This configuration interface setup allows for multiple postgresql
73+databases: you can use one for a virtual table, one for an access
74+table, and one for an aliases table if you want.
75+
76+Since sites that have a need for multiple mail exchangers may enjoy
77+the convenience of using a networked mailer database, but do not want
78+to introduce a single point of failure to their system, we've included
79+the ability to have postfix reference multiple hosts for access to a
80+single pgsql map. This will work if sites set up mirrored pgsql
81+databases on two or more hosts. Whenever queries fail with an error
82+at one host, the rest of the hosts will be tried in order. Each host
83+that is in an error state will undergo a reconnection attempt every so
84+often, and if no pgsql server hosts are reachable, then mail will be
85+deferred until atleast one of those hosts is reachable.
86+
87+Performance of postfix with pgsql has not been thoroughly tested,
88+however, we have found it to be stable. Busy mail servers using pgsql
89+maps will generate lots of concurrent pgsql clients, so the pgsql
90+server(s) should be run with this fact in mind. Any further
91+performance information, in addition to any feedback is most welcome.
0b72d562 92--- postfix-2.0.16.orig/src/util/dict_open.c 2003-11-08 20:10:08.000000000 +0100
93+++ postfix-2.0.16/src/util/dict_open.c 2003-11-08 20:11:44.000000000 +0100
94@@ -178,6 +178,7 @@
f512ae96
JB
95 #include <dict_ni.h>
96 #include <dict_ldap.h>
97 #include <dict_mysql.h>
98+#include <dict_pgsql.h>
99 #include <dict_pcre.h>
100 #include <dict_regexp.h>
101 #include <dict_static.h>
0b72d562 102@@ -231,6 +232,9 @@
f512ae96
JB
103 #ifdef HAS_MYSQL
104 DICT_TYPE_MYSQL, dict_mysql_open,
105 #endif
106+#ifdef HAS_PGSQL
107+ DICT_TYPE_PGSQL, dict_pgsql_open,
108+#endif
109 #ifdef HAS_PCRE
110 DICT_TYPE_PCRE, dict_pcre_open,
111 #endif
0b72d562 112--- postfix-2.0.16.orig/src/util/dict_pgsql.c 1970-01-01 01:00:00.000000000 +0100
113+++ postfix-2.0.16/src/util/dict_pgsql.c 2003-11-08 20:11:44.000000000 +0100
f512ae96
JB
114@@ -0,0 +1,675 @@
115+
116+/*++
117+/* NAME
118+/* dict_pgsql 3
119+/* SUMMARY
120+/* dictionary manager interface to db files
121+/* SYNOPSIS
122+/* #include <dict.h>
123+/* #include <dict_pgsql.h>
124+/*
125+/* DICT *dict_pgsql_open(name, dummy, unused_dict_flags)
126+/* const char *name;
127+/* int dummy;
128+/* int unused_dict_flags;
129+/* DESCRIPTION
130+/* dict_pgsql_open() creates a dictionary of type 'pg'. This
131+/* dictionary is an interface for the postfix key->value mappings
132+/* to pgsql. The result is a pointer to the installed dictionary,
133+/* or a null pointer in case of problems.
134+/*
135+/* The pgsql dictionary can manage multiple connections to different
136+/* sql servers on different hosts. It assumes that the underlying data
137+/* on each host is identical (mirrored) and maintains one connection
138+/* at any given time. If any connection fails, any other available
139+/* ones will be opened and used. The intent of this feature is to eliminate
140+/* a single point of failure for mail systems that would otherwise rely
141+/* on a single pgsql server.
142+/*
143+/* Arguments:
144+/* .IP name
145+/* The path of the PostgreSQL configuration file. The file encodes a number of
146+/* pieces of information: username, password, databasename, table,
147+/* select_field, where_field, and hosts. For example, if you want the map to
148+/* reference databases of the name "your_db" and execute a query like this:
149+/* select forw_addr from aliases where alias like '<some username>' against
150+/* any database called "vmailer_info" located on hosts host1.some.domain and
151+/* host2.some.domain, logging in as user "vmailer" and password "passwd" then
152+/* the configuration file should read:
153+/*
154+/* user = vmailer
155+/* password = passwd
156+/* DBname = vmailer_info
157+/* table = aliases
158+/* select_field = forw_addr
159+/* where_field = alias
160+/* hosts = host1.some.domain host2.some.domain
161+/*
162+/* .IP other_name
163+/* reference for outside use.
164+/* .IP unusued_flags
165+/* unused flags
166+/* SEE ALSO
167+/* dict(3) generic dictionary manager
168+/* AUTHOR(S)
169+/* Mathieu Arnold
170+/* Absolight
171+/* mat@absolight.com
172+/*
173+/* based on dict_mysql by
174+/*
175+/* Scott Cotton
176+/* IC Group, Inc.
177+/* scott@icgroup.com
178+/*
179+/* Joshua Marcus
180+/* IC Group, Inc.
181+/* josh@icgroup.com
182+/*--*/
183+
184+/* System library. */
185+#include "sys_defs.h"
186+
187+#ifdef HAS_PGSQL
188+#include <sys/socket.h>
189+#include <netinet/in.h>
190+#include <arpa/inet.h>
191+#include <netdb.h>
192+#include <stdio.h>
193+#include <string.h>
194+#include <stdlib.h>
195+#include <syslog.h>
196+#include <time.h>
197+#include <libpq-fe.h>
198+
199+/* Utility library. */
200+#include "dict.h"
201+#include "msg.h"
202+#include "mymalloc.h"
203+#include "dict_pgsql.h"
204+#include "argv.h"
205+#include "vstring.h"
206+#include "split_at.h"
207+#include "find_inet.h"
208+
209+/* need some structs to help organize things */
210+typedef struct
211+{
212+ PGconn *db;
213+ char *hostname;
214+ int stat; /* STATUNTRIED | STATFAIL | STATCUR */
215+ time_t ts; /* used for attempting reconnection
216+ * every so often if a host is down */
217+} HOST;
218+
219+typedef struct
220+{
221+ int len_hosts; /* number of hosts */
222+ HOST *db_hosts; /* the hosts on which the databases
223+ * reside */
224+} PLPGSQL;
225+
226+typedef struct
227+{
228+ char *username;
229+ char *password;
230+ char *dbname;
231+ char *table;
232+ char *select_field;
233+ char *where_field;
234+ char *additional_conditions;
235+ char **hostnames;
236+ int len_hosts;
237+} PGSQL_NAME;
238+
239+typedef struct
240+{
241+ DICT dict;
242+ PLPGSQL *pldb;
243+ PGSQL_NAME *name;
244+} DICT_PGSQL;
245+
246+#define STATACTIVE 0
247+#define STATFAIL 1
248+#define STATUNTRIED 2
249+#define RETRY_CONN_INTV 60 /* 1 minute */
250+
251+/* internal function declarations */
252+static PLPGSQL *plpgsql_init (char *hostnames[], int);
253+static PGresult *plpgsql_query (PLPGSQL *, const char *, char *, char *,
254+
255+ char *);
256+static void plpgsql_dealloc (PLPGSQL *);
257+static void plpgsql_down_host (HOST *);
258+static void plpgsql_connect_single (HOST *, char *, char *, char *);
259+static int plpgsql_ready_reconn (HOST *);
260+static const char *dict_pgsql_lookup (DICT *, const char *);
261+DICT *dict_pgsql_open (const char *, int, int);
262+static void dict_pgsql_close (DICT *);
263+static PGSQL_NAME *pgsqlname_parse (const char *);
264+static HOST host_init (char *);
265+void pgsql_escape_string (char *escaped, const char *name, int len);
266+
267+
268+
269+/**********************************************************************
270+ * public interface dict_pgsql_lookup
271+ * find database entry return 0 if no alias found, set dict_errno
272+ * on errors to DICT_ERRBO_RETRY and set dict_errno to 0 on success
273+ *********************************************************************/
274+static const char *dict_pgsql_lookup (DICT *dict, const char *name)
275+{
276+ PGresult *query_res;
277+ char *field;
278+ DICT_PGSQL *dict_pgsql;
279+ PLPGSQL *pldb;
280+ static VSTRING *result;
281+ static VSTRING *query = 0;
282+ int i,
283+ j,
284+ numrows;
285+ char *name_escaped = 0;
286+
287+ dict_pgsql = (DICT_PGSQL *) dict;
288+ pldb = dict_pgsql->pldb;
289+ /* initialization for query */
290+ query = vstring_alloc (24);
291+ vstring_strcpy (query, "");
292+ if (
293+ (name_escaped =
294+ (char *) mymalloc ((sizeof (char) * (strlen (name) * 2) + 1))) ==
295+ NULL)
296+ {
297+ msg_fatal ("dict_pgsql_lookup: out of memory.");
298+ }
299+ /* prepare the query */
300+ pgsql_escape_string (name_escaped, name, (unsigned int) strlen (name));
301+ vstring_sprintf (query, "select %s from %s where %s = '%s' %s",
302+ dict_pgsql->name->select_field, dict_pgsql->name->table,
303+ dict_pgsql->name->where_field, name_escaped,
304+ dict_pgsql->name->additional_conditions);
305+ if (msg_verbose)
306+ msg_info ("dict_pgsql_lookup using sql query: %s",
307+ vstring_str (query));
308+ /* free mem associated with preparing the query */
309+ myfree (name_escaped);
310+ /* do the query - set dict_errno & cleanup if there's an error */
311+ if ((query_res = plpgsql_query (pldb,
312+ vstring_str (query),
313+ dict_pgsql->name->dbname,
314+ dict_pgsql->name->username,
315+ dict_pgsql->name->password)) == 0)
316+ {
317+ dict_errno = DICT_ERR_RETRY;
318+ vstring_free (query);
319+ return 0;
320+ }
321+ dict_errno = 0;
322+ /* free the vstring query */
323+ vstring_free (query);
324+ numrows = PQntuples (query_res);
325+ if (msg_verbose)
326+ msg_info ("dict_pgsql_lookup: retrieved %d rows", numrows);
327+ if (numrows == 0)
328+ {
329+ PQclear (query_res);
330+ return 0;
331+ }
332+ if (result == 0)
333+ result = vstring_alloc (10);
334+ vstring_strcpy (result, "");
335+ for (i = 0; i < numrows; i++)
336+ {
337+ if (i > 0)
338+ vstring_strcat (result, ",");
339+ for (j = 0; j < PQnfields (query_res); j++)
340+ {
341+ if (j > 0)
342+ vstring_strcat (result, ",");
343+ field = PQgetvalue (query_res, i, j);
344+ vstring_strcat (result, field);
345+ if (msg_verbose > 1)
346+ msg_info ("dict_pgsql_lookup: retrieved field: %d: %s", j,
347+ field);
348+ }
349+ }
350+ PQclear (query_res);
351+ return vstring_str (result);
352+}
353+
354+/*
355+ * plpgsql_query - process a PGSQL query. Return PGresult* on success.
356+ * On failure, log failure and try other db instances.
357+ * on failure of all db instances, return 0;
358+ * close unnecessary active connections
359+ */
360+
361+static PGresult *plpgsql_query (PLPGSQL * PLDB,
362+ const char *query,
363+ char *dbname, char *username, char *password)
364+{
365+ int i;
366+ HOST *host;
367+ PGresult *res = 0;
368+ ExecStatusType status;
369+
370+ for (i = 0; i < PLDB->len_hosts; i++)
371+ {
372+ /* can't deal with typing or reading PLDB->db_hosts[i] over & over */
373+ host = &(PLDB->db_hosts[i]);
374+ if (msg_verbose > 1)
375+ msg_info ("dict_pgsql: trying host %s stat %d, last res %p",
376+ host->hostname, host->stat, res);
377+
378+ /* answer already found */
379+ if (res != 0 && host->stat == STATACTIVE)
380+ {
381+ if (msg_verbose)
382+ msg_info
383+ ("dict_pgsql: closing unnessary connection to %s",
384+ host->hostname);
385+ plpgsql_down_host (host);
386+ }
387+ /* try to connect for the first time if we don't have a result yet */
388+ if (res == 0 && host->stat == STATUNTRIED)
389+ {
390+ if (msg_verbose)
391+ msg_info ("dict_pgsql: attempting to connect to host %s",
392+ host->hostname);
393+ plpgsql_connect_single (host, dbname, username, password);
394+ }
395+
396+ /*
397+ * try to reconnect if we don't have an answer and the host had a
398+ * prob in the past and it's time for it to reconnect
399+ */
400+ if (res == 0 && host->stat == STATFAIL
401+ && host->ts < time ((time_t *) 0))
402+ {
403+ if (msg_verbose)
404+ msg_info
405+ ("dict_pgsql: attempting to reconnect to host %s",
406+ host->hostname);
407+ plpgsql_connect_single (host, dbname, username, password);
408+ }
409+
410+ /*
411+ * if we don't have a result and the current host is marked active,
412+ * try the query. If the query fails, mark the host STATFAIL
413+ */
414+ if (res == 0 && host->stat == STATACTIVE)
415+ {
416+ res = PQexec (host->db, query);
417+ status = PQresultStatus (res);
418+ if (res
419+ && (status = PGRES_COMMAND_OK
420+ || status == PGRES_TUPLES_OK))
421+ {
422+ if (msg_verbose)
423+ msg_info
424+ ("dict_pgsql: successful query from host %s",
425+ host->hostname);
426+ }
427+ else
428+ {
429+ msg_warn ("%s", PQerrorMessage (host->db));
430+ plpgsql_down_host (host);
431+ }
432+ }
433+ }
434+ return res;
435+}
436+
437+/*
438+ * plpgsql_connect_single -
439+ * used to reconnect to a single database when one is down or none is
440+ * connected yet. Log all errors and set the stat field of host accordingly
441+ */
442+static void
443+plpgsql_connect_single (HOST *host, char *dbname, char *username,
444+ char *password)
445+{
446+ char *destination = host->hostname;
447+ char *hostname = 0;
448+ char *service;
449+ VSTRING *conninfo = vstring_alloc (100);
450+ char *conn;
451+ unsigned port = 0;
452+
453+ /*
454+ * Ad-hoc parsing code. Expect "unix:pathname" or "inet:host:port", where
455+ * both "inet:" and ":port" are optional.
456+ */
457+ if (strncmp (destination, "unix:", 5) == 0)
458+ {
459+ vstring_sprintf_append (conninfo, "host=%s ", destination + 5);
460+ }
461+ else
462+ {
463+ if (strncmp (destination, "inet:", 5) == 0)
464+ destination += 5;
465+ hostname = mystrdup (destination);
466+ if ((service = split_at (hostname, ':')) != 0)
467+ {
468+ port = ntohs (find_inet_port (service, "tcp"));
469+ vstring_sprintf_append (conninfo, "host='%s' port='%d'",
470+ hostname, port);
471+ }
472+ else
473+ {
474+ vstring_sprintf_append (conninfo, "host='%s'", hostname);
475+ }
476+ }
477+
478+ vstring_sprintf_append (conninfo, " dbname='%s' user='%s' password='%s'", dbname,
479+ username, password);
480+ conn = vstring_export (conninfo);
481+
482+ host->db = PQconnectdb (conn);
483+
484+ if ((host->db != NULL) && (PQstatus (host->db) == CONNECTION_OK))
485+ {
486+ if (msg_verbose)
487+ msg_info ("dict_pgsql: successful connection to host %s",
488+ host->hostname);
489+ host->stat = STATACTIVE;
490+ }
491+ else
492+ {
493+ msg_warn ("%s", PQerrorMessage (host->db));
494+ plpgsql_down_host (host);
495+ }
496+ if (hostname)
497+ myfree (hostname);
498+ myfree (conn);
499+}
500+
501+/*
502+ * plpgsql_down_host - mark a HOST down update ts if marked down
503+ * for the first time so that we'll know when to retry the connection
504+ */
505+static void plpgsql_down_host (HOST *host)
506+{
507+ if (host->stat != STATFAIL)
508+ {
509+ host->ts = time ((time_t *) 0) + RETRY_CONN_INTV;
510+ host->stat = STATFAIL;
511+ }
512+ PQfinish (host->db);
513+ host->db = 0;
514+}
515+
516+/**********************************************************************
517+ * public interface dict_pgsql_open
518+ * create association with database with appropriate values
519+ * parse the map's config file
520+ * allocate memory
521+ **********************************************************************/
522+DICT *dict_pgsql_open (const char *name, int unused_open_flags,
523+ int dict_flags)
524+{
525+ DICT_PGSQL *dict_pgsql;
526+ int connections;
527+
528+ dict_pgsql = (DICT_PGSQL *) dict_alloc (DICT_TYPE_PGSQL, name,
529+ sizeof (DICT_PGSQL));
530+ dict_pgsql->dict.lookup = dict_pgsql_lookup;
531+ dict_pgsql->dict.close = dict_pgsql_close;
532+ dict_pgsql->dict.flags = dict_flags | DICT_FLAG_FIXED;
533+ dict_pgsql->name = pgsqlname_parse (name);
534+ dict_pgsql->pldb = plpgsql_init (dict_pgsql->name->hostnames,
535+ dict_pgsql->name->len_hosts);
536+ if (dict_pgsql->pldb == NULL)
537+ msg_fatal ("couldn't intialize pldb!\n");
538+ dict_register (name, (DICT *) dict_pgsql);
539+ return (DICT_DEBUG (&dict_pgsql->dict));
540+}
541+
542+/* pgsqlname_parse - parse pgsql configuration file */
543+static PGSQL_NAME *pgsqlname_parse (const char *pgsqlcf_path)
544+{
545+ int i;
546+ char *nameval;
547+ char *hosts;
548+ PGSQL_NAME *name = (PGSQL_NAME *) mymalloc (sizeof (PGSQL_NAME));
549+ ARGV *hosts_argv;
550+ VSTRING *opt_dict_name;
551+
552+ /*
553+ * setup a dict containing info in the pgsql cf file. the dict has a
554+ * name, and a path. The name must be distinct from the path, or the
555+ * dict interface gets confused. The name must be distinct for two
556+ * different paths, or the configuration info will cache across different
557+ * pgsql maps, which can be confusing.
558+ */
559+ opt_dict_name = vstring_alloc (64);
560+ vstring_sprintf (opt_dict_name, "pgsql opt dict %s", pgsqlcf_path);
561+ dict_load_file (vstring_str (opt_dict_name), pgsqlcf_path);
562+ /* pgsql username lookup */
563+ if (
564+ (nameval =
565+ (char *) dict_lookup (vstring_str (opt_dict_name), "user")) == NULL)
566+ name->username = mystrdup ("");
567+ else
568+ name->username = mystrdup (nameval);
569+ if (msg_verbose)
570+ msg_info ("pgsqlname_parse(): set username to '%s'", name->username);
571+ /* password lookup */
572+ if (
573+ (nameval =
574+ (char *) dict_lookup (vstring_str (opt_dict_name),
575+ "password")) == NULL)
576+ name->password = mystrdup ("");
577+ else
578+ name->password = mystrdup (nameval);
579+ if (msg_verbose)
580+ msg_info ("pgsqlname_parse(): set password to '%s'", name->password);
581+
582+ /* database name lookup */
583+ if (
584+ (nameval =
585+ (char *) dict_lookup (vstring_str (opt_dict_name),
586+ "dbname")) == NULL)
587+
588+
589+
590+ msg_fatal ("%s: pgsql options file does not include database name",
591+ pgsqlcf_path);
592+ else
593+ name->dbname = mystrdup (nameval);
594+ if (msg_verbose)
595+ msg_info ("pgsqlname_parse(): set database name to '%s'",
596+ name->dbname);
597+
598+ /* table lookup */
599+ if (
600+ (nameval =
601+ (char *) dict_lookup (vstring_str (opt_dict_name), "table")) == NULL)
602+ msg_fatal ("%s: pgsql options file does not include table name",
603+ pgsqlcf_path);
604+ else
605+ name->table = mystrdup (nameval);
606+ if (msg_verbose)
607+ msg_info ("pgsqlname_parse(): set table name to '%s'", name->table);
608+
609+ /* select field lookup */
610+ if (
611+ (nameval =
612+ (char *) dict_lookup (vstring_str (opt_dict_name),
613+ "select_field")) == NULL)
614+
615+
616+
617+ msg_fatal ("%s: pgsql options file does not include select field",
618+ pgsqlcf_path);
619+ else
620+ name->select_field = mystrdup (nameval);
621+ if (msg_verbose)
622+ msg_info ("pgsqlname_parse(): set select_field to '%s'",
623+ name->select_field);
624+
625+ /* where field lookup */
626+ if (
627+ (nameval =
628+ (char *) dict_lookup (vstring_str (opt_dict_name),
629+ "where_field")) == NULL)
630+ msg_fatal ("%s: pgsql options file does not include where field",
631+ pgsqlcf_path);
632+ else
633+ name->where_field = mystrdup (nameval);
634+ if (msg_verbose)
635+ msg_info ("pgsqlname_parse(): set where_field to '%s'",
636+ name->where_field);
637+
638+ /* additional conditions */
639+ if (
640+ (nameval =
641+ (char *) dict_lookup (vstring_str (opt_dict_name),
642+ "additional_conditions")) == NULL)
643+ name->additional_conditions = mystrdup ("");
644+ else
645+ name->additional_conditions = mystrdup (nameval);
646+ if (msg_verbose)
647+ msg_info ("pgsqlname_parse(): set additional_conditions to '%s'",
648+ name->additional_conditions);
649+
650+ /* pgsql server hosts */
651+ if (
652+ (nameval =
653+ (char *) dict_lookup (vstring_str (opt_dict_name), "hosts")) == NULL)
654+ hosts = mystrdup ("");
655+ else
656+ hosts = mystrdup (nameval);
657+ /* coo argv interface */
658+ hosts_argv = argv_split (hosts, " ,\t\r\n");
659+
660+ if (hosts_argv->argc == 0)
661+ { /* no hosts specified,
662+ * default to 'localhost' */
663+ if (msg_verbose)
664+ msg_info
665+ ("pgsqlname_parse(): no hostnames specified, defaulting to 'localhost'");
666+ argv_add (hosts_argv, "localhost", ARGV_END);
667+ argv_terminate (hosts_argv);
668+ }
669+ name->len_hosts = hosts_argv->argc;
670+ name->hostnames =
671+
672+ (char **) mymalloc ((sizeof (char *)) * name->len_hosts);
673+ i = 0;
674+ for (i = 0; hosts_argv->argv[i] != NULL; i++)
675+ {
676+ name->hostnames[i] = mystrdup (hosts_argv->argv[i]);
677+ if (msg_verbose)
678+ msg_info
679+ ("pgsqlname_parse(): adding host '%s' to list of pgsql server hosts",
680+ name->hostnames[i]);
681+ }
682+ myfree (hosts);
683+ vstring_free (opt_dict_name);
684+ argv_free (hosts_argv);
685+ return name;
686+}
687+
688+
689+/*
690+ * plpgsql_init - initalize a PGSQL database.
691+ * Return NULL on failure, or a PLPGSQL * on success.
692+ */
693+static PLPGSQL *plpgsql_init (char *hostnames[], int len_hosts)
694+{
695+ PLPGSQL *PLDB;
696+ int i;
697+ HOST host;
698+
699+ if ((PLDB = (PLPGSQL *) mymalloc (sizeof (PLPGSQL))) == NULL)
700+ {
701+ msg_fatal ("mymalloc of pldb failed");
702+ }
703+ PLDB->len_hosts = len_hosts;
704+ if ((PLDB->db_hosts = (HOST *) mymalloc (sizeof (HOST) * len_hosts))
705+ == NULL)
706+ return NULL;
707+
708+ for (i = 0; i < len_hosts; i++)
709+ {
710+ PLDB->db_hosts[i] = host_init (hostnames[i]);
711+ }
712+ return PLDB;
713+}
714+
715+
716+/* host_init - initialize HOST structure */
717+static HOST host_init (char *hostname)
718+{
719+ HOST host;
720+
721+ host.stat = STATUNTRIED;
722+ host.hostname = mystrdup (hostname);
723+ host.db = 0;
724+ host.ts = 0;
725+ return host;
726+}
727+
728+/**********************************************************************
729+ * public interface dict_pgsql_close
730+ * unregister, disassociate from database, freeing appropriate memory
731+ **********************************************************************/
732+static void dict_pgsql_close (DICT *dict)
733+{
734+ int i;
735+ DICT_PGSQL *dict_pgsql = (DICT_PGSQL *) dict;
736+
737+ plpgsql_dealloc (dict_pgsql->pldb);
738+ myfree (dict_pgsql->name->username);
739+ myfree (dict_pgsql->name->password);
740+ myfree (dict_pgsql->name->dbname);
741+ myfree (dict_pgsql->name->table);
742+ myfree (dict_pgsql->name->select_field);
743+ myfree (dict_pgsql->name->where_field);
744+ myfree (dict_pgsql->name->additional_conditions);
745+ for (i = 0; i < dict_pgsql->name->len_hosts; i++)
746+ {
747+ myfree (dict_pgsql->name->hostnames[i]);
748+ }
749+ myfree ((char *) dict_pgsql->name->hostnames);
750+ myfree ((char *) dict_pgsql->name);
751+ dict_free (dict);
752+}
753+
754+/* plpgsql_dealloc - free memory associated with PLPGSQL close databases */
755+static void plpgsql_dealloc (PLPGSQL * PLDB)
756+{
757+ int i;
758+
759+ for (i = 0; i < PLDB->len_hosts; i++)
760+ {
761+ if (PLDB->db_hosts[i].db)
762+ PQfinish (PLDB->db_hosts[i].db);
763+ myfree (PLDB->db_hosts[i].hostname);
764+ }
765+ myfree ((char *) PLDB->db_hosts);
766+ myfree ((char *) (PLDB));
767+}
768+
769+/* pgsql_escape_string - replace mysql_escape_string */
770+void pgsql_escape_string (char *escaped, const char *name, int len)
771+{
772+ int i,
773+ j;
774+
775+ for (i = 0, j = 0; i <= len; i++, j++)
776+ {
777+ if ((name[i] == '\'') || (name[i] == '\\'))
778+ {
779+ escaped[j] = '\\';
780+ j++;
781+ }
782+ escaped[j] = name[i];
783+ }
784+}
785+
786+
787+
788+#endif
789+
0b72d562 790--- postfix-2.0.16.orig/src/util/dict_pgsql.h 1970-01-01 01:00:00.000000000 +0100
791+++ postfix-2.0.16/src/util/dict_pgsql.h 2003-11-08 20:11:44.000000000 +0100
f512ae96
JB
792@@ -0,0 +1,41 @@
793+#ifndef _DICT_PGSQL_H_INCLUDED_
794+#define _DICT_PGSQL_H_INCLUDED_
795+
796+/*++
797+/* NAME
798+/* dict_pgsql 3h
799+/* SUMMARY
800+/* dictionary manager interface to pgsql databases
801+/* SYNOPSIS
802+/* #include <dict_pgsql.h>
803+/* DESCRIPTION
804+/* .nf
805+
806+ /*
807+ * Utility library.
808+ */
809+#include <dict.h>
810+
811+ /*
812+ * External interface.
813+ */
814+#define DICT_TYPE_PGSQL "pgsql"
815+
816+extern DICT *dict_pgsql_open (const char *, int, int);
817+
818+/* LICENSE
819+/* .ad
820+/* .fi
821+/* The Secure Mailer license must be distributed with this software.
822+/* AUTHOR(S)
823+/* Scott Cotton
824+/* IC Group, Inc.
825+/* scott@icgroup.com
826+/*
827+/* Joshua Marcus
828+/* IC Group, Inc.
829+/* josh@icgroup.com
830+/*--*/
831+
832+#endif
833+
0b72d562 834--- postfix-2.0.16.orig/src/util/Makefile.in 2003-11-08 20:10:08.000000000 +0100
835+++ postfix-2.0.16/src/util/Makefile.in 2003-11-08 20:12:29.000000000 +0100
836@@ -4,7 +4,7 @@
837 chroot_uid.c clean_env.c close_on_exec.c concatenate.c ctable.c \
838 dict.c dict_alloc.c dict_db.c dict_dbm.c dict_debug.c dict_env.c \
839 dict_ht.c dict_mysql.c dict_ni.c dict_nis.c \
840- dict_nisplus.c dict_open.c dict_pcre.c dict_regexp.c dict_static.c \
841+ dict_nisplus.c dict_open.c dict_pcre.c dict_pgsql.c dict_regexp.c dict_static.c \
842 dict_tcp.c dict_unix.c dir_forest.c doze.c duplex_pipe.c \
843 environ.c events.c exec_command.c fifo_listen.c fifo_trigger.c \
844 file_limit.c find_inet.c fsspace.c fullname.c get_domainname.c \
845@@ -60,7 +60,7 @@
846 HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
847 connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
848 dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
849- dict_nisplus.h dict_pcre.h dict_regexp.h dict_static.h dict_tcp.h \
850+ dict_nisplus.h dict_pcre.h dict_pgsql.h dict_regexp.h dict_static.h dict_tcp.h \
851 dict_unix.h dir_forest.h events.h exec_command.h find_inet.h \
852 fsspace.h fullname.h get_domainname.h get_hostname.h hex_quote.h \
853 htable.h inet_addr_host.h inet_addr_list.h inet_addr_local.h \
854@@ -86,6 +86,7 @@
855 INCL =
856 PCRESO = dict_pcre.so
857 MYSQLSO = dict_mysql.so
858+PGSQLSO = dict_pgsql.so
859 LIB = libutil.a
860 TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
861 fifo_rdonly_bug fifo_rdwr_bug fifo_trigger fsspace fullname \
862@@ -98,7 +99,7 @@
863
864 LIB_DIR = ../../lib
865 INC_DIR = ../../include
866-LIBS = $(LIB_DIR)/$(LIB) $(LIB_DIR)/$(PCRESO) $(LIB_DIR)/$(MYSQLSO)
867+LIBS = $(LIB_DIR)/$(LIB) $(LIB_DIR)/$(PCRESO) $(LIB_DIR)/$(MYSQLSO) $(LIB_DIR)/$(PGSQLSO)
868
869 .c.o:; $(CC) -fPIC $(CFLAGS) -c $*.c
870
871@@ -115,6 +116,9 @@
872 $(MYSQLSO): dict_mysql.o
873 gcc -shared -Wl,-soname,dict_mysql.so -o $@ $? -lmysqlclient -L. -lutil
874
875+$(PGSQLSO): dict_pgsql.o
876+ gcc -shared -Wl,-soname,dict_pgsql.so -o $@ $? -lpq -lcrypt -L. -lutil
877+
878 $(LIB): $(OBJS)
879 gcc -shared -Wl,-soname,libpostfix-util.so.1 -o $(LIB) $(OBJS) -ldl
880
881@@ -127,6 +131,9 @@
882 $(LIB_DIR)/$(MYSQLSO): $(MYSQLSO)
883 cp $(MYSQLSO) $(LIB_DIR)
884
885+$(LIB_DIR)/$(PGSQLSO): $(PGSQLSO)
886+ cp $(PGSQLSO) $(LIB_DIR)
887+
888 update: $(LIBS) $(HDRS)
889 -for i in $(HDRS); \
890 do \
891@@ -149,7 +156,7 @@
892 lint $(SRCS)
893
894 clean:
895- rm -f *.o $(LIB) $(PCRESO) $(MYSQLSO) *core $(TESTPROG) \
896+ rm -f *.o $(LIB) $(PCRESO) $(MYSQLSO) $(PGSQLSO) *core $(TESTPROG) \
897 junk $(MAKES) *.tmp
898 rm -rf printfck
899
900@@ -591,6 +598,8 @@
901 dict_ldap.o: sys_defs.h
902 dict_mysql.o: dict_mysql.c
903 dict_mysql.o: sys_defs.h
904+dict_pgsql.o: dict_pgsql.c
905+dict_pgsql.o: sys_defs.h
906 dict_ni.o: dict_ni.c
907 dict_ni.o: sys_defs.h
908 dict_nis.o: dict_nis.c
909@@ -632,6 +641,7 @@
910 dict_open.o: dict_ni.h
911 dict_open.o: dict_ldap.h
912 dict_open.o: dict_mysql.h
913+dict_open.o: dict_pgsql.h
914 dict_open.o: dict_pcre.h
915 dict_open.o: dict_regexp.h
916 dict_open.o: dict_static.h
This page took 0.203147 seconds and 4 git commands to generate.