# HG changeset patch # User Timo Sirainen # Date 1138312860 -7200 # Node ID cbe5c6772e0daec30b2f645075f8c3cd8934ea8d # Parent a490e6657329d5cdb320bc94703fb9e748c2d11b Added support for dynamically building SQL drivers. diff -r a490e6657329 -r cbe5c6772e0d INSTALL --- 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 _init and _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 diff -r a490e6657329 -r cbe5c6772e0d configure.in --- 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 ** diff -r a490e6657329 -r cbe5c6772e0d src/auth/main.c --- 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(); diff -r a490e6657329 -r cbe5c6772e0d src/lib-dict/dict-sql.c --- 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); } diff -r a490e6657329 -r cbe5c6772e0d src/lib-sql/.cvsignore --- 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 diff -r a490e6657329 -r cbe5c6772e0d src/lib-sql/Makefile.am --- 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 diff -r a490e6657329 -r cbe5c6772e0d src/lib-sql/driver-mysql.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 #include #include @@ -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 diff -r a490e6657329 -r cbe5c6772e0d src/lib-sql/driver-pgsql.c --- 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 #include #include @@ -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 diff -r a490e6657329 -r cbe5c6772e0d src/lib-sql/driver-sqlite.c --- 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 #include #include @@ -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 diff -r a490e6657329 -r cbe5c6772e0d src/lib-sql/sql-api-private.h --- 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 diff -r a490e6657329 -r cbe5c6772e0d src/lib-sql/sql-api.c --- 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); diff -r a490e6657329 -r cbe5c6772e0d src/lib-sql/sql-api.h --- 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. */