changeset 3943:cbe5c6772e0d HEAD

Added support for dynamically building SQL drivers.
author Timo Sirainen <tss@iki.fi>
date Fri, 27 Jan 2006 00:01:00 +0200
parents a490e6657329
children e7aff159a0d3
files INSTALL configure.in src/auth/main.c src/lib-dict/dict-sql.c src/lib-sql/.cvsignore src/lib-sql/Makefile.am src/lib-sql/driver-mysql.c src/lib-sql/driver-pgsql.c src/lib-sql/driver-sqlite.c src/lib-sql/sql-api-private.h src/lib-sql/sql-api.c src/lib-sql/sql-api.h
diffstat 12 files changed, 199 insertions(+), 63 deletions(-) [+]
line wrap: on
line diff
--- a/INSTALL	Thu Jan 26 23:08:53 2006 +0200
+++ b/INSTALL	Fri Jan 27 00:01:00 2006 +0200
@@ -117,20 +117,12 @@
 
 gcc -shared -fPIC -DHAVE_CONFIG_H -DUSERDB_LDAP -DPASSDB_LDAP \
 -I../.. -I../lib -I../lib-settings \
-db-ldap.c userdb-ldap.c passdb-ldap.c -o ldap.so \
-../lib-settings/libsettings.a -lldap
-
-gcc -shared -fPIC -DHAVE_CONFIG_H -DUSERDB_PGSQL -DPASSDB_PGSQL \
--I../.. -I../lib -I../lib-settings -I/usr/include/postgresql \
-db-pgsql.c userdb-pgsql.c passdb-pgsql.c -o pgsql.so \
-../lib-settings/libsettings.a -L/usr/lib/postgresql -lpq
+db-ldap.c userdb-ldap.c passdb-ldap.c -o ldap.so -lldap
 
 gcc -shared -fPIC -DHAVE_CONFIG_H -DUSERDB_VPOPMAIL -DPASSDB_VPOPMAIL \
 -I../.. -I../lib userdb-vpopmail.c passdb-vpopmail.c -o vpopmail.so \
 -lvpopmail
 
-Including libsettings.a in ldap.so and pgsql.so is kind of annoying, but it's
-not needed elsewhere in dovecot-auth.
 
 Dynamic IMAP and POP3 Modules
 -----------------------------
@@ -139,3 +131,18 @@
 *.so modules from directory pointed by imap_modules or pop3_modules. These
 modules can do anything, they're only expected to contain <module name>_init
 and <module name>_deinit functions which are called.
+
+
+Dynamic SQL drivers
+-------------------
+
+Currently SQL drivers are only used by dovecot-auth, so you could place
+them into same directory with auth plugins.
+
+gcc -shared -fPIC -DHAVE_CONFIG_H -DBUILD_PGSQL \
+-I../.. -I../lib -I../lib-settings -I/usr/include/postgresql \
+driver-pgsql.c -o driver_pgsql.so -L/usr/lib/postgresql -lpq
+
+gcc -shared -fPIC -DHAVE_CONFIG_H -DBUILD_MYSQL \
+-I../.. -I../lib -I../lib-settings -I/usr/include/mysql \
+driver-mysql.c -o driver_mysql.so -lmysqlclient
--- a/configure.in	Thu Jan 26 23:08:53 2006 +0200
+++ b/configure.in	Fri Jan 27 00:01:00 2006 +0200
@@ -257,11 +257,21 @@
 AM_CONDITIONAL(BUILD_DELIVER, test "$want_deliver" = "yes")
 
 AC_ARG_WITH(storages,
-[  --with-storages         Build specified mail storage formats (maildir,mbox)], [
+[  --with-storages         Build with specified mail storage formats (maildir,mbox)], [
 	mail_storages=`echo "$withval"|sed 's/,/ /g'` ],
 	mail_storages="maildir mbox dbox")
 AC_SUBST(mail_storages)
 
+AC_ARG_WITH(sql-drivers,
+[  --with-sql-drivers      Build with specified SQL drivers (all)], [
+	sql_drivers=`echo "$withval"|sed 's/,/ /g'` ],
+	sql_driver="all")
+
+if test "$sql_driver" = "all"; then
+  all_sql_drivers=yes
+  sql_driver=
+fi
+
 AC_ARG_WITH(moduledir,
 [  --with-moduledir=DIR    Base directory for dynamically loadable modules],
 	moduledir="$withval",
@@ -1380,9 +1390,11 @@
 			fi
 			SQL_LIBS="$SQL_LIBS -lpq"
 			AC_DEFINE(HAVE_PGSQL,, Build with PostgreSQL support)
-			have_sql=yes
-			userdb="$userdb pgsql"
-			passdb="$passdb pgsql"
+			found_sql_drivers="$found_sql_drivers pgsql"
+
+                        if test "$all_sql_drivers" = "yes"; then
+			  sql_drivers="$sql_drivers pgsql"
+			fi
 		])
 		CPPFLAGS=$old_CPPFLAGS
 	])
@@ -1447,9 +1459,7 @@
 			])
 			
 			AC_DEFINE(HAVE_MYSQL,, Build with MySQL support)
-			have_sql=yes
-			userdb="$userdb mysql"
-			passdb="$passdb mysql"
+			found_sql_drivers="$found_sql_drivers mysql"
 		])
 		CPPFLAGS=$old_CPPFLAGS
 	fi
@@ -1498,9 +1508,7 @@
 			SQL_LIBS="$SQL_LIBS $sqlite_lib"
 
 			AC_DEFINE(HAVE_SQLITE,, Build with SQLite3 support)
-			have_sql=yes
-			userdb="$userdb sqlite"
-			passdb="$passdb sqlite"
+			found_sql_drivers="$found_sql_drivers sqlite"
 		])
 		CPPFLAGS=$old_CPPFLAGS
 	fi
@@ -1508,10 +1516,16 @@
 	LIBS=$old_LIBS
 fi
 
-if test "$have_sql" = yes; then
+if test "$found_sql_drivers" != ""; then
+	if test "$all_sql_drivers" = "yes"; then
+	  sql_drivers="$found_sql_drivers"
+	fi
+
 	AC_DEFINE(PASSDB_SQL,, Build with SQL support)
 	AC_DEFINE(USERDB_SQL,, Build with SQL support)
 	AUTH_LIBS="$AUTH_LIBS $SQL_LIBS"
+	passdb="$userdb sql"
+	userdb="$userdb sql"
 fi
 
 if test $want_vpopmail = yes; then
@@ -1625,6 +1639,22 @@
 
 
 dnl **
+dnl ** SQL drivers
+dnl **
+
+for driver in $sql_drivers; do
+  if test "$driver" = "pgsql"; then
+    AC_DEFINE(BUILD_PGSQL,, Built-in PostgreSQL support)
+  elif test "$driver" = "mysql"; then
+    AC_DEFINE(BUILD_MYSQL,, Built-in MySQL support)
+  elif test "$driver" = "sqlite"; then
+    AC_DEFINE(BUILD_SQLITE,, Built-in SQLite support)
+  fi
+done
+
+AC_SUBST(sql_drivers)
+
+dnl **
 dnl ** capabilities
 dnl **
 
--- a/src/auth/main.c	Thu Jan 26 23:08:53 2006 +0200
+++ b/src/auth/main.c	Fri Jan 27 00:01:00 2006 +0200
@@ -7,6 +7,7 @@
 #include "lib-signals.h"
 #include "restrict-access.h"
 #include "fd-close-on-exec.h"
+#include "sql-api.h"
 #include "randgen.h"
 #include "password-scheme.h"
 #include "mech.h"
@@ -185,6 +186,10 @@
 	/* Open /dev/urandom before chrooting */
 	random_init();
 
+	/* Load built-in SQL drivers (if any) */
+	sql_drivers_init();
+	sql_drivers_register_all();
+
 	/* Initialize databases so their configuration files can be readable
 	   only by root. Also load all modules here. */
 	auth = auth_preinit();
@@ -276,6 +281,7 @@
 	mech_deinit();
 
         password_schemes_deinit();
+	sql_drivers_deinit();
 	random_deinit();
 
 	lib_signals_deinit();
--- a/src/lib-dict/dict-sql.c	Thu Jan 26 23:08:53 2006 +0200
+++ b/src/lib-dict/dict-sql.c	Fri Jan 27 00:01:00 2006 +0200
@@ -1,6 +1,7 @@
 /* Copyright (C) 2005 Timo Sirainen */
 
 #include "lib.h"
+#include "array.h"
 #include "istream.h"
 #include "str.h"
 #include "strescape.h"
@@ -288,15 +289,16 @@
 
 void dict_sql_register(void)
 {
-	int i, count;
+        const struct sql_db *const *drivers;
+	unsigned int i, count;
 
 	/* @UNSAFE */
-	for (count = 0; sql_db_drivers[count] != NULL; count++) ;
-	dict_sql_classes = i_new(struct dict, count);
+	drivers = array_get(&sql_drivers, &count);
+	dict_sql_classes = i_new(struct dict, count + 1);
 
 	for (i = 0; i < count; i++) {
 		dict_sql_classes[i] = sql_dict;
-		dict_sql_classes[i].name = sql_db_drivers[i]->name;
+		dict_sql_classes[i].name = drivers[i]->name;
 
 		dict_class_register(&dict_sql_classes[i]);
 	}
@@ -306,7 +308,7 @@
 {
 	int i;
 
-	for (i = 0; sql_db_drivers[i] != NULL; i++)
+	for (i = 0; dict_sql_classes[i].name != NULL; i++)
 		dict_class_unregister(&dict_sql_classes[i]);
 	i_free(dict_sql_classes);
 }
--- a/src/lib-sql/.cvsignore	Thu Jan 26 23:08:53 2006 +0200
+++ b/src/lib-sql/.cvsignore	Fri Jan 27 00:01:00 2006 +0200
@@ -6,3 +6,4 @@
 Makefile
 Makefile.in
 so_locations
+sql-drivers-register.c
--- a/src/lib-sql/Makefile.am	Thu Jan 26 23:08:53 2006 +0200
+++ b/src/lib-sql/Makefile.am	Fri Jan 27 00:01:00 2006 +0200
@@ -1,5 +1,7 @@
 noinst_LIBRARIES = libsql.a
 
+sql_drivers = @sql_drivers@
+
 AM_CPPFLAGS = \
 	-I$(top_srcdir)/src/lib \
 	$(SQL_CFLAGS)
@@ -8,8 +10,28 @@
 	driver-mysql.c \
 	driver-pgsql.c \
 	driver-sqlite.c \
-	sql-api.c
+	sql-api.c \
+	sql-drivers-register.c
 
 noinst_HEADERS = \
 	sql-api.h \
 	sql-api-private.h
+
+sql-drivers-register.c: Makefile
+	rm -f $@
+	echo '/* this file automatically generated by Makefile */' >$@
+	echo '#include "lib.h"' >>$@
+	echo '#include "sql-api.h"' >>$@
+	for i in $(sql_drivers) ; do \
+		echo "extern struct sql_db driver_$${i}_db;" >>$@ ; \
+	done
+	echo 'void sql_drivers_register_all(void) {' >>$@
+	for i in $(sql_drivers) ; do \
+		echo "sql_driver_register(&driver_$${i}_db);" >>$@ ; \
+	done
+	echo '}' >>$@
+
+DISTFILES = $(DIST_COMMON) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
+
+distclean-generic:
+	rm -f Makefile sql-drivers-register.c
--- a/src/lib-sql/driver-mysql.c	Thu Jan 26 23:08:53 2006 +0200
+++ b/src/lib-sql/driver-mysql.c	Fri Jan 27 00:01:00 2006 +0200
@@ -5,7 +5,7 @@
 #include "str.h"
 #include "sql-api-private.h"
 
-#ifdef HAVE_MYSQL
+#ifdef BUILD_MYSQL
 #include <stdlib.h>
 #include <unistd.h>
 #include <time.h>
@@ -68,6 +68,7 @@
 	string_t *queries;
 };
 
+extern struct sql_db driver_mysql_db;
 extern struct sql_result driver_mysql_result;
 extern struct sql_result driver_mysql_error_result;
 
@@ -231,7 +232,7 @@
 		i_fatal("mysql: No hosts given in connect string");
 }
 
-static struct sql_db *driver_mysql_init(const char *connect_string)
+static struct sql_db *_driver_mysql_init(const char *connect_string)
 {
 	struct mysql_db *db;
 	pool_t pool;
@@ -249,7 +250,7 @@
 	return &db->api;
 }
 
-static void driver_mysql_deinit(struct sql_db *_db)
+static void _driver_mysql_deinit(struct sql_db *_db)
 {
 	struct mysql_db *db = (struct mysql_db *)_db;
 	struct mysql_connection *conn;
@@ -573,8 +574,8 @@
 struct sql_db driver_mysql_db = {
 	"mysql",
 
-	driver_mysql_init,
-	driver_mysql_deinit,
+	_driver_mysql_init,
+	_driver_mysql_deinit,
 	driver_mysql_get_flags,
         driver_mysql_connect_all,
 	driver_mysql_exec,
@@ -621,4 +622,18 @@
 
 	FALSE
 };
+
+void driver_mysql_init(void);
+void driver_mysql_deinit(void);
+
+void driver_mysql_init(void)
+{
+	sql_driver_register(&driver_mysql_db);
+}
+
+void driver_mysql_deinit(void)
+{
+	sql_driver_unregister(&driver_mysql_db);
+}
+
 #endif
--- a/src/lib-sql/driver-pgsql.c	Thu Jan 26 23:08:53 2006 +0200
+++ b/src/lib-sql/driver-pgsql.c	Fri Jan 27 00:01:00 2006 +0200
@@ -5,7 +5,7 @@
 #include "ioloop-internal.h" /* kind of dirty, but it should be fine.. */
 #include "sql-api-private.h"
 
-#ifdef HAVE_PGSQL
+#ifdef BUILD_PGSQL
 #include <stdlib.h>
 #include <time.h>
 #include <libpq-fe.h>
@@ -66,6 +66,7 @@
 	unsigned int failed:1;
 };
 
+extern struct sql_db driver_pgsql_db;
 extern struct sql_result driver_pgsql_result;
 
 static void queue_send_next(struct pgsql_db *db);
@@ -166,7 +167,7 @@
 	}
 }
 
-static struct sql_db *driver_pgsql_init(const char *connect_string)
+static struct sql_db *_driver_pgsql_init(const char *connect_string)
 {
 	struct pgsql_db *db;
 
@@ -179,7 +180,7 @@
 	return &db->api;
 }
 
-static void driver_pgsql_deinit(struct sql_db *_db)
+static void _driver_pgsql_deinit(struct sql_db *_db)
 {
 	struct pgsql_db *db = (struct pgsql_db *)_db;
 
@@ -737,8 +738,8 @@
 struct sql_db driver_pgsql_db = {
 	"pgsql",
 
-	driver_pgsql_init,
-	driver_pgsql_deinit,
+	_driver_pgsql_init,
+	_driver_pgsql_deinit,
         driver_pgsql_get_flags,
 	driver_pgsql_connect,
 	driver_pgsql_exec,
@@ -769,4 +770,17 @@
 	FALSE
 };
 
+void driver_pgsql_init(void);
+void driver_pgsql_deinit(void);
+
+void driver_pgsql_init(void)
+{
+	sql_driver_register(&driver_pgsql_db);
+}
+
+void driver_pgsql_deinit(void)
+{
+	sql_driver_unregister(&driver_pgsql_db);
+}
+
 #endif
--- a/src/lib-sql/driver-sqlite.c	Thu Jan 26 23:08:53 2006 +0200
+++ b/src/lib-sql/driver-sqlite.c	Fri Jan 27 00:01:00 2006 +0200
@@ -4,7 +4,7 @@
 #include "str.h"
 #include "sql-api-private.h"
 
-#ifdef HAVE_SQLITE
+#ifdef BUILD_SQLITE
 #include <stdlib.h>
 #include <time.h>
 #include <sqlite3.h>
@@ -34,6 +34,7 @@
 	unsigned int failed:1;
 };
 
+extern struct sql_db driver_sqlite_db;
 extern struct sql_result driver_sqlite_result;
 extern struct sql_result driver_sqlite_error_result;
 
@@ -58,7 +59,7 @@
 	}
 }
 
-static struct sql_db *driver_sqlite_init(const char *connect_string)
+static struct sql_db *_driver_sqlite_init(const char *connect_string)
 {
 	struct sqlite_db *db;
 	pool_t pool;
@@ -75,7 +76,7 @@
 	return &db->api;
 }
 
-static void driver_sqlite_deinit(struct sql_db *_db)
+static void _driver_sqlite_deinit(struct sql_db *_db)
 {
 	struct sqlite_db *db = (struct sqlite_db *)_db;
 
@@ -331,8 +332,8 @@
 struct sql_db driver_sqlite_db = {
 	"sqlite",
 
-	driver_sqlite_init,
-	driver_sqlite_deinit,
+	_driver_sqlite_init,
+	_driver_sqlite_deinit,
 	driver_sqlite_get_flags,
 	driver_sqlite_connect,
 	driver_sqlite_exec,
@@ -379,4 +380,17 @@
 	FALSE
 };
 
+void driver_sqlite_init(void);
+void driver_sqlite_deinit(void);
+
+void driver_sqlite_init(void)
+{
+	sql_driver_register(&driver_sqlite_db);
+}
+
+void driver_sqlite_deinit(void)
+{
+	sql_driver_unregister(&driver_sqlite_db);
+}
+
 #endif
--- a/src/lib-sql/sql-api-private.h	Thu Jan 26 23:08:53 2006 +0200
+++ b/src/lib-sql/sql-api-private.h	Fri Jan 27 00:01:00 2006 +0200
@@ -54,10 +54,7 @@
 	struct sql_db *db;
 };
 
-extern struct sql_db driver_mysql_db;
-extern struct sql_db driver_pgsql_db;
-extern struct sql_db driver_sqlite_db;
-
+extern array_t ARRAY_DEFINE(sql_drivers, const struct sql_db *);
 extern struct sql_result sql_not_connected_result;
 
 #endif
--- a/src/lib-sql/sql-api.c	Thu Jan 26 23:08:53 2006 +0200
+++ b/src/lib-sql/sql-api.c	Fri Jan 27 00:01:00 2006 +0200
@@ -1,29 +1,50 @@
-/* Copyright (c) 2004 Timo Sirainen */
+/* Copyright (c) 2004-2006 Timo Sirainen */
 
 #include "lib.h"
+#include "array.h"
 #include "sql-api-private.h"
 
-struct sql_db *sql_db_drivers[] = {
-#ifdef HAVE_PGSQL
-	&driver_pgsql_db,
-#endif
-#ifdef HAVE_MYSQL
-	&driver_mysql_db,
-#endif
-#ifdef HAVE_SQLITE
-	&driver_sqlite_db,
-#endif
-	NULL
-};
+array_t ARRAY_DEFINE(sql_drivers, const struct sql_db *);
+
+void sql_drivers_init(void)
+{
+	ARRAY_CREATE(&sql_drivers, default_pool, const struct sql_db *, 8);
+}
+
+void sql_drivers_deinit(void)
+{
+	array_free(&sql_drivers);
+}
+
+void sql_driver_register(const struct sql_db *driver)
+{
+	array_append(&sql_drivers, &driver, 1);
+}
+
+void sql_driver_unregister(const struct sql_db *driver)
+{
+	const struct sql_db *const *drivers;
+	unsigned int i, count;
+
+	drivers = array_get(&sql_drivers, &count);
+	for (i = 0; i < count; i++) {
+		if (drivers[i] == driver) {
+			array_delete(&sql_drivers, i, 1);
+			break;
+		}
+	}
+}
 
 struct sql_db *sql_init(const char *db_driver,
 			const char *connect_string __attr_unused__)
 {
-	int i;
+	const struct sql_db *const *drivers;
+	unsigned int i, count;
 
-	for (i = 0; sql_db_drivers[i] != NULL; i++) {
-		if (strcmp(db_driver, sql_db_drivers[i]->name) == 0)
-			return sql_db_drivers[i]->init(connect_string);
+	drivers = array_get(&sql_drivers, &count);
+	for (i = 0; i < count; i++) {
+		if (strcmp(db_driver, drivers[i]->name) == 0)
+			return drivers[i]->init(connect_string);
 	}
 
 	i_fatal("Unknown database driver '%s'", db_driver);
--- a/src/lib-sql/sql-api.h	Thu Jan 26 23:08:53 2006 +0200
+++ b/src/lib-sql/sql-api.h	Fri Jan 27 00:01:00 2006 +0200
@@ -15,7 +15,14 @@
 typedef void sql_query_callback_t(struct sql_result *result, void *context);
 typedef void sql_commit_callback_t(const char *error, void *context);
 
-extern struct sql_db *sql_db_drivers[];
+void sql_drivers_init(void);
+void sql_drivers_deinit(void);
+
+/* register all built-in SQL drivers */
+void sql_drivers_register_all(void);
+
+void sql_driver_register(const struct sql_db *driver);
+void sql_driver_unregister(const struct sql_db *driver);
 
 /* Initialize database connections. db_driver is the database driver name,
    eg. "mysql" or "pgsql". connect_string is driver-specific. */