Commit 0cb608de 0cb608de0ac37bfe71e06f4d592c232c78ac4db1 by Sergey Poznyakoff

Reimplement DBM support.

* lib/mu_dbm.c: Remove.
* lib/mu_dbm.h: Remove.
* lib/Makefile.am: Remove mu_dbm.[ch].
* include/mailutils/sys/dbm.h: New file.
* include/mailutils/sys/Makefile.am: Add dbm.h
* include/mailutils/dbm.h: New file.
* include/mailutils/Makefile.am (pkginclude_HEADERS): Add dbm.h.
* include/mailutils/types.hin (mu_dbm_file_t): New data type.

* libmu_dbm/Makefile.am: New file.
* libmu_dbm/berkeley.c: New file.
* libmu_dbm/close.c: New file.
* libmu_dbm/create.c: New file.
* libmu_dbm/datumfree.c: New file.
* libmu_dbm/dbm.c: New file.
* libmu_dbm/delete.c: New file.
* libmu_dbm/destroy.c: New file.
* libmu_dbm/errstr.c: New file.
* libmu_dbm/fetch.c: New file.
* libmu_dbm/firstkey.c: New file.
* libmu_dbm/gdbm.c: New file.
* libmu_dbm/mudbm.h: New file.
* libmu_dbm/ndbm.c: New file.
* libmu_dbm/nextkey.c: New file.
* libmu_dbm/open.c: New file.
* libmu_dbm/safety.c: New file.
* libmu_dbm/store.c: New file.

* Makefile.am [MU_COND_DBM]: Define LIBMU_DBM_DIR
(SUBDIRS): Add $(LIBMU_DBM_DIR)
* configure.ac: Revamp DBM support: several database types can
be specified at once.
(AC_CONFIG_FILES): Build libmu_dbm/Makefile

* libmu_sieve/extensions/vacation.c: Remove inclusion of mu_dbm.h.
* maidag/Makefile.am (maidag_LDADD): Add DBM libraries.
* maidag/maidag.c: ENABLE_DBM instead of USE_DBM
* maidag/maidag.h: Include <mailutils/dbm.h> instead of mu_dbm.h.
* maidag/mailquota.c (dbm_retrieve_quota): Rewrite using libmu_dbm
library calls.
* mu/Makefile.am [MU_COND_DBM]: Define DBM_C.
(MODULES): Add $(DBM_C).
(AM_CPPFLAGS): Define DBMLIBS.
* mu/ldflags.c (NEEDAUTH): Change definition.
(lib_descr) <weight>: New member. All uses changed.
(add_entry): Null arguments ignored.
(mutool_ldflags): Rewrite traversal of lib_descr.
* mu/dbm.c: New file.

* pop3d/Makefile.am (pop3d_LDADD, popauth_LDADD): Add DBM libraries.
* pop3d/apop.c: Rewrite using libmu_dbm library calls.
* pop3d/bulletin.c: Likewise.
* pop3d/logindelay.c: Likewise.
* pop3d/pop3d.c: Change USE_DBM to ENABLE_DBM.
* pop3d/pop3d.h: Include mailutils/dbm.h instead of mu_dbm.h
* pop3d/popauth.c: Rewrite using libmu_dbm library calls.

* include/mailutils/cctype.h (MU_CTYPE_ENDLN): New character class.
(mu_isendln): New macro.
* libmailutils/string/muctype.c (mu_c_tab): Mark \r and \n as
MU_CTYPE_ENDLN.
1 parent f70ebb8c
......@@ -83,6 +83,10 @@ if MU_COND_SUPPORT_CXX
LIBMU_CPP_DIR = libmu_cpp
endif
if MU_COND_DBM
LIBMU_DBM_DIR = libmu_dbm
endif
SUBDIRS = . \
mu-aux\
include\
......@@ -99,6 +103,7 @@ SUBDIRS = . \
$(LIBMU_CPP_DIR)\
$(GINT_DIR)\
$(LIBMU_SCM_DIR)\
$(LIBMU_DBM_DIR)\
libmu_sieve\
$(PYTHON_DIR)\
doc\
......
......@@ -88,7 +88,7 @@ AM_PROG_LIBTOOL
## Predefine several variables used to display configuration status
status_pam=no
status_ltdl=no
status_dbm=no
status_dbm=
status_gsasl=no
status_mysql=no
status_pgsql=no
......@@ -354,22 +354,31 @@ AH_BOTTOM(
# define MU_PATH_MAILDIR PATH_MAILDIR "/"
#endif])
use_dbm=no
##################################
# DBM Support
##################################
AC_SUBST(DBMLIBS)
AC_SUBST(DBMLIB_DEPENDENCY)
AC_SUBST(DBMINCLUDES)
enable_dbm=no
disable_dbm=no
AC_ARG_WITH([gdbm],
AC_HELP_STRING([--with-gdbm],
[use GNU DBM]),
[
case "${withval}" in
yes) use_dbm=GDBM ;;
no) use_dbm=no ;;
yes) enable_dbm="$enable_dbm GDBM";;
no) disable_dbm="$disable_dbm GDBM";;
*) AC_MSG_ERROR(bad value ${withval} for --with-gdbm) ;;
esac])
## Support --with-db2 for backward compatibility
if test "${with_db2+set}" = set; then
case "${with_db2}" in
yes) use_dbm=BDB2 ;;
no) use_dbm=no ;;
yes) enable_dbm="$enable_dbm BDB2";;
no) disable_dbm="$disable_dbm BDB2";;
*) AC_MSG_ERROR(bad value ${with_db2} for --with-db2) ;;
esac
fi
......@@ -379,9 +388,9 @@ AC_ARG_WITH([berkeley-db],
[use Berkeley DB]),
[
case "${withval}" in
yes) use_dbm=BDB ;;
no) use_dbm=no ;;
*) use_dbm=BDB="${withval}";;
yes) enable_dbm="$enable_dbm BDB";;
no) disable_dbm="$disable_dbm BDB";;
*) enable_dbm="$enable_dbm BDB=${withval}";;
esac])
AC_ARG_WITH([ndbm],
......@@ -389,8 +398,8 @@ AC_ARG_WITH([ndbm],
[use NDBM]),
[
case "${withval}" in
yes) use_dbm=NDBM ;;
no) use_dbm=no ;;
yes) enable_dbm="$enable_dbm NDBM";;
no) disable_dbm="$disable_dbm NDBM";;
*) AC_MSG_ERROR(bad value ${withval} for --with-ndbm) ;;
esac])
......@@ -399,11 +408,174 @@ AC_ARG_WITH([tokyocabinet],
[use Tokyo Cabinet]),
[
case "${withval}" in
yes) use_dbm=TC ;;
no) use_dbm=no ;;
yes) enable_dbm="$enable_dbm TC";;
no) disable_dbm="$disable_dbm TC";;
*) AC_MSG_ERROR(bad value ${withval} for --with-tokyocabinet) ;;
esac])
dnl Check for DBM
AH_TEMPLATE([WITH_BDB],
[Define to the major version of Berkeley DB library to use])
status_bdb=no
## Set the variable status_bdb to $1 if:
##
## 1. Function $3 is defined in the library $2
## 2. Header file db.h is available
##
## Then check if the major version, minor version and patchlevel of the
## library matches those from the header. If so, define WITH_BDB
## to the version (i.e. $1 with all dots removed). Otherwise, report
## an error and stop.
##
check_bdb() {
ver=`echo $1 | tr -d '.'`
major=`expr $ver : '\(.\).*'`
status_bdb=no
AC_CHECK_LIB($2, $3,
[AC_CHECK_HEADERS(db.h)
if test $ac_cv_header_db_h = yes; then
DBMLIBS="$DBMLIBS -l$2"
MU_DB2_CURSOR
status_bdb="$1"
fi])
if test "$status_bdb" = no; then
:
else
save_LIBS=$LIBS
LIBS="$LIBS $DBMLIBS"
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([#include "db.h"],
[int v_major, v_minor, v_patch;
db_version(&v_major, &v_minor, &v_patch);
return !(DB_VERSION_MAJOR == $major
&& v_major == DB_VERSION_MAJOR
&& v_minor == DB_VERSION_MINOR
&& v_patch == DB_VERSION_PATCH);
])],
[],
[status_bdb=no])
LIBS=$save_LIBS
if test "$status_bdb" != no; then
AC_DEFINE_UNQUOTED(WITH_BDB,$ver)
fi
fi
}
## Check for the Berkeley DB library version $1, assuming Slackware-like
## installation layout (header files in /usr/incude/db$vn and library named
## libdb-$version.so, where $version is the library version and $vn is
## $version with all dots removed.
##
check_slackware_bdb() {
dir=db`echo $1|tr -d '.'`
save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS -I/usr/include/$dir"
check_bdb "$1" db-$1 db_create
CPPFLAGS=$save_CPPFLAGS
if test "$status_bdb" = "$1"; then
DBMINCLUDES="$DBMINCLUDES -I/usr/include/$dir"
status_dbm="$status_dbm,Berkeley DB v. $status_bdb"
fi
}
check_dbm_impl() {
case "$1" in
GDBM)
AC_CHECK_LIB(gdbm, gdbm_open,
[AC_CHECK_HEADERS(gdbm.h,
AC_DEFINE(WITH_GDBM,1,
[Enable use of GNU DBM library]))
DBMLIBS="$DBMLIBS -lgdbm"
status_dbm="$status_dbm,GDBM"]);;
BDB2) check_bdb 2 db db_open
test -n "$status_bdb" && status_dbm="$status_dbm,Berkeley DB v. $status_bdb";;
BDB) for version in 4 3 2
do
case $version in
4|3) func=db_create;;
2) func=db_open;;
esac
check_bdb $version db $func
if test "$status_bdb" != no; then
status_dbm="$status_dbm,Berkeley DB v. $status_bdb"
break;
fi
done;;
BDB=*)
name=`expr $use_dbm : 'BDB=\(.*\)'`
case $name in
[[0-9]]*) check_slackware_bdb $name;;
*) for version in 4 3 2
do
case $version in
4|3) func=db_create;;
2) func=db_open;;
esac
check_bdb $version $name $func
if test "$status_bdb" != no; then
status_dbm="$status_dbm,Berkeley DB v. $status_bdb"
break;
fi
done
;;
esac
;;
NDBM)
has_ndbm=no
AC_CHECK_HEADERS(ndbm.h,[has_ndbm=yes])
if test $has_ndbm = yes; then
AC_CHECK_FUNC(dbm_open,:,[has_ndbm=no])
if test $has_ndbm = no; then
AC_CHECK_LIB(ndbm, dbm_open,
[DBMLIBS="$DBMLIBS -lndbm"])
fi
fi
if test $has_ndbm = yes; then
AC_DEFINE(WITH_NDBM,1,[Enable use of NDBM])
status_dbm="$status_dbm,NDBM"
fi
;;
TC)
AC_CHECK_LIB(tokyocabinet, tchdbnew,
[AC_CHECK_HEADERS(tchdb.h,
AC_DEFINE(WITH_TOKYOCABINET,1,
[Enable use of Tokyo Cabinet]))
DBMLIB_DEPENDENCY="$DBMLIB_DEPENDENCY -lz -lbz2 -lrt"
DBMLIBS="$DBMLIBS -ltokyocabinet"
status_dbm="$status_dbm,Tokyo Cabinet"]);;
esac
}
if test "$enable_dbm" = no; then
enable_dbm="GDBM BDB TC NDBM"
fi
for impl in $enable_dbm
do
if echo "$disable_dbm" | grep $impl >/dev/null; then
: # skip it
else
check_dbm_impl $impl
fi
done
if test -z "$status_dbm"; then
status_dbm=no
else
status_dbm=`echo "$status_dbm" | sed 's/^,//'`
AC_DEFINE([ENABLE_DBM], 1, [Define if DBM interface is compiled])
fi
AM_CONDITIONAL([MU_COND_DBM], [test "$status_dbm" != no])
####################
AC_MSG_CHECKING(for log facility)
log_facility="LOG_MAIL"
AC_ARG_WITH([log-facility],
......@@ -938,129 +1110,6 @@ AH_BOTTOM([
# define rl_completion_matches completion_matches
#endif])
dnl Check for DBM
AH_TEMPLATE([WITH_BDB],
[Define to the major version of Berkeley DB library to use])
## Set the variable status_dbm to $1 if:
##
## 1. Function $3 is defined in the library $2
## 2. Header file db.h is available
##
## Then check if the major version, minor version and patchlevel of the
## library matches those from the header. If so, define WITH_BDB
## to the version (i.e. $1 with all dots removed). Otherwise, report
## an error and stop.
##
check_bdb() {
ver=`echo $1 | tr -d '.'`
major=`expr $ver : '\(.\).*'`
AC_CHECK_LIB($2, $3,
[AC_CHECK_HEADERS(db.h)
if test $ac_cv_header_db_h = yes; then
LIBS="$LIBS -l$2"
MU_DB2_CURSOR
status_dbm=$1
fi])
if test "$status_dbm" = no; then
:
else
AC_RUN_IFELSE(
[AC_LANG_PROGRAM([#include "db.h"],
[int v_major, v_minor, v_patch;
db_version(&v_major, &v_minor, &v_patch);
return !(DB_VERSION_MAJOR == $major
&& v_major == DB_VERSION_MAJOR
&& v_minor == DB_VERSION_MINOR
&& v_patch == DB_VERSION_PATCH);
])],
[],
[status_dbm=no])
if test "$status_dbm" != no; then
AC_DEFINE_UNQUOTED(WITH_BDB,$ver)
fi
fi
}
## Check for the Berkeley DB library version $1, assuming Slackware-like
## installation layout (header files in /usr/incude/db$vn and library named
## libdb-$version.so, where $version is the library version and $vn is
## $version with all dots removed.
##
check_slackware_bdb() {
dir=db`echo $1|tr -d '.'`
save_CPPFLAGS=$CPPFLAGS
CPPFLAGS="$CPPFLAGS -I/usr/include/$dir"
check_bdb "$1" db-$1 db_create
CPPFLAGS=$save_CPPFLAGS
if test "$status_dbm" = "$1"; then
MU_COMMON_INCLUDES="$MU_COMMON_INCLUDES -I/usr/include/$dir"
fi
}
case "$use_dbm" in
GDBM)
AC_CHECK_LIB(gdbm, gdbm_open,
[AC_CHECK_HEADERS(gdbm.h,
AC_DEFINE(WITH_GDBM,1,
[Enable use of GNU DBM library]))
LIBS="$LIBS -lgdbm"
status_dbm="GDBM"]);;
BDB2) check_bdb 2 db db_open
test -n "$status_dbm" && status_dbm="Berkeley DB v. $status_dbm";;
BDB) for version in 4 3 2
do
case $version in
4|3) func=db_create;;
2) func=db_open;;
esac
check_bdb $version db $func
if test "$status_dbm" != no; then
status_dbm="Berkeley DB v. $status_dbm"
break;
fi
done;;
BDB=*)
name=`expr $use_dbm : 'BDB=\(.*\)'`
case $name in
[[0-9]]*) check_slackware_bdb $name;;
*) for version in 4 3 2
do
case $version in
4|3) func=db_create;;
2) func=db_open;;
esac
check_bdb $version $name $func
if test "$status_dbm" != no; then
status_dbm="Berkeley DB v. $status_dbm"
break;
fi
done
;;
esac
;;
NDBM)
AC_CHECK_LIB(ndbm, dbm_open,
[AC_CHECK_HEADERS(ndbm.h,
AC_DEFINE(WITH_NDBM,1,
[Enable use of NDBM]))
LIBS="$LIBS -lndbm"
status_dbm="NDBM"]);;
TC)
AC_CHECK_LIB(tokyocabinet, tchdbnew,
[AC_CHECK_HEADERS(tchdb.h,
AC_DEFINE(WITH_TOKYOCABINET,1,
[Enable use of Tokyo Cabinet]))
LIBS="$LIBS -ltokyocabinet -lz -lbz2 -lrt"
status_dbm="Tokyo Cabinet"]);;
esac
AC_SUBST(POPAUTH)
if test "$status_dbm" != no; then
POPAUTH='popauth$(EXEEXT)'
......@@ -1397,6 +1446,7 @@ AC_CONFIG_FILES([
libmu_cpp/Makefile
libmu_scm/Makefile
libmu_scm/mailutils/Makefile
libmu_dbm/Makefile
libmu_sieve/Makefile
libmu_sieve/extensions/Makefile
libproto/Makefile
......
......@@ -39,6 +39,7 @@ pkginclude_HEADERS = \
cidr.h\
cstr.h\
daemon.h\
dbm.h\
debug.h\
diag.h\
envelope.h\
......
......@@ -35,6 +35,7 @@ extern "C" {
#define MU_CTYPE_PUNCT 0x100
#define MU_CTYPE_SPACE 0x200
#define MU_CTYPE_XLETR 0x400
#define MU_CTYPE_ENDLN 0x800
#define MU_C_TAB_MAX 128
......@@ -56,6 +57,7 @@ extern int mu_c_tab[MU_C_TAB_MAX];
#define mu_isalnum(c) mu_c_is_class (c, MU_CTYPE_ALPHA|MU_CTYPE_DIGIT)
#define mu_isascii(c) (((unsigned)c) < MU_C_TAB_MAX)
#define mu_isblank(c) ((c) == ' ' || (c) == '\t')
#define mu_isendln(c) mu_c_is_class (c, MU_CTYPE_ENDLN)
#define mu_tolower(c) \
({ int __c = (c); \
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011
Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef _MAILUTILS_DBM_H
#define _MAILUTILS_DBM_H
#include <mailutils/types.h>
struct mu_dbm_datum
{
char *mu_dptr; /* Data pointer */
size_t mu_dsize; /* Data size */
void *mu_data; /* Implementation-dependent data */
struct mu_dbm_impl *mu_sys; /* Pointer to implementation */
};
struct mu_dbm_impl
{
char *_dbm_name;
int (*_dbm_file_safety) (mu_dbm_file_t db, int mode, uid_t owner);
int (*_dbm_get_fd) (mu_dbm_file_t db, int *pag, int *dir);
int (*_dbm_open) (mu_dbm_file_t db, int flags, int mode);
int (*_dbm_close) (mu_dbm_file_t db);
int (*_dbm_fetch) (mu_dbm_file_t db, struct mu_dbm_datum const *key,
struct mu_dbm_datum *ret);
int (*_dbm_store) (mu_dbm_file_t db, struct mu_dbm_datum const *key,
struct mu_dbm_datum const *contents, int replace);
int (*_dbm_delete) (mu_dbm_file_t db,
struct mu_dbm_datum const *key);
int (*_dbm_firstkey) (mu_dbm_file_t db, struct mu_dbm_datum *ret);
int (*_dbm_nextkey) (mu_dbm_file_t db, struct mu_dbm_datum *ret);
void (*_dbm_datum_free) (struct mu_dbm_datum *datum);
char const *(*_dbm_strerror) (mu_dbm_file_t db);
};
extern mu_url_t mu_dbm_hint;
int mu_dbm_register (struct mu_dbm_impl *impl);
int mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db);
int mu_dbm_create (char *name, mu_dbm_file_t *db);
int mu_dbm_close (mu_dbm_file_t db);
void mu_dbm_datum_free (struct mu_dbm_datum *datum);
int mu_dbm_delete (mu_dbm_file_t db, struct mu_dbm_datum const *key);
void mu_dbm_destroy (mu_dbm_file_t *pdb);
int mu_dbm_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
struct mu_dbm_datum *ret);
int mu_dbm_store (mu_dbm_file_t db, struct mu_dbm_datum const *key,
struct mu_dbm_datum const *contents, int replace);
int mu_dbm_firstkey (mu_dbm_file_t db, struct mu_dbm_datum *ret);
int mu_dbm_nextkey (mu_dbm_file_t db, struct mu_dbm_datum *ret);
int mu_dbm_open (mu_dbm_file_t db, int flags, int mode);
int mu_dbm_safety_get_owner (mu_dbm_file_t db, uid_t *uid);
int mu_dbm_safety_get_flags (mu_dbm_file_t db, int *flags);
int mu_dbm_safety_set_owner (mu_dbm_file_t db, uid_t uid);
int mu_dbm_safety_set_flags (mu_dbm_file_t db, int flags);
int mu_dbm_safety_check (mu_dbm_file_t db);
char const *mu_dbm_strerror (mu_dbm_file_t db);
int mu_dbm_get_fd (mu_dbm_file_t db, int *pag, int *dir);
int mu_dbm_impl_iterator (mu_iterator_t *itr);
#endif
......@@ -21,6 +21,7 @@ sysinclude_HEADERS = \
attribute.h\
auth.h\
body.h\
dbm.h\
debcat.h\
envelope.h\
file_stream.h\
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifndef _MAILUTILS_SYS_DBM_H
# define _MAILUTILS_SYS_DBM_H
union _mu_dbm_errno
{
int n;
void *p;
};
struct _mu_dbm_file
{
char *db_name; /* Database name */
void *db_descr; /* Database descriptor */
int db_safety_flags; /* Safety checks */
uid_t db_owner; /* Database owner UID */
struct mu_dbm_impl *db_sys; /* Pointer to the database implementation */
union _mu_dbm_errno db_errno;
};
#endif
......@@ -75,6 +75,7 @@ struct _mu_assoc;
struct _mu_acl;
struct _mu_server;
struct _mu_tcp_server;
struct _mu_dbm_file;
struct mu_sockaddr; /* defined in mailutils/sockaddr.h */
struct mu_cidr; /* defined in mailutils/cidr.h */
......@@ -121,6 +122,7 @@ typedef struct _mu_opool *mu_opool_t;
typedef struct _mu_progmailer *mu_progmailer_t;
typedef struct _mu_secret *mu_secret_t;
typedef struct _mu_mime_io_buffer *mu_mime_io_buffer_t;
typedef struct _mu_dbm_file *mu_dbm_file_t;
typedef void (*mu_onexit_t) (void*);
typedef unsigned int mu_debug_handle_t;
......
......@@ -24,7 +24,6 @@ libmuaux_a_SOURCES += \
daemon.c\
mailcap.c\
manlock.c\
mu_dbm.c\
signal.c\
strexit.c\
tcpwrap.c\
......@@ -34,7 +33,6 @@ libmuaux_a_SOURCES += \
noinst_HEADERS +=\
mailcap.h\
muaux.h\
mu_dbm.h\
tcpwrap.h
EXTRA_DIST += utmp.c
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2006, 2007, 2009, 2010, 2011
Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include <errno.h>
#include <mailutils/errno.h>
#include <mailutils/stream.h>
#include <mu_dbm.h>
#include <xalloc.h>
int
mu_fcheck_perm (int fd, int mode)
{
struct stat st;
if (mode == 0)
return 0;
if (fstat (fd, &st) == -1)
{
if (errno == ENOENT)
return 0;
else
return 1;
}
if ((st.st_mode & 0777) != mode)
{
errno = MU_ERR_UNSAFE_PERMS;
return 1;
}
return 0;
}
int
mu_check_perm (const char *name, int mode)
{
struct stat st;
if (mode == 0)
return 0;
if (stat (name, &st) == -1)
{
if (errno == ENOENT)
return 0;
else
return 1;
}
if ((st.st_mode & 0777) != mode)
{
errno = MU_ERR_UNSAFE_PERMS;
return 1;
}
return 0;
}
static char *
make_db_name (const char *name, const char *suffix)
{
int nlen = strlen (name);
int slen = strlen (suffix);
char *p;
if (nlen > slen && strcmp (name + nlen - slen, suffix) == 0)
p = xstrdup (name);
else
{
p = xmalloc (strlen (name) + slen + 1);
strcat (strcpy (p, name), suffix);
}
return p;
}
#if defined(WITH_GDBM)
#define DB_SUFFIX ".db"
int
mu_dbm_stat (char *name, struct stat *sb)
{
int rc;
char *pfname = make_db_name (name, DB_SUFFIX);
rc = stat (pfname, sb);
free (pfname);
return rc;
}
int
mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode)
{
int f;
char *pfname = make_db_name (name, DB_SUFFIX);
if (mu_check_perm (pfname, mode))
{
free (pfname);
return -1;
}
switch (flags)
{
case MU_STREAM_CREAT:
f = GDBM_NEWDB;
break;
case MU_STREAM_READ:
f = GDBM_READER;
break;
case MU_STREAM_RDWR:
f = GDBM_WRCREAT;
break;
default:
free (pfname);
errno = EINVAL;
return 1;
}
*db = gdbm_open (pfname, 512, f, mode, NULL);
free (pfname);
return *db == NULL;
}
int
mu_dbm_close (DBM_FILE db)
{
gdbm_close(db);
return 0;
}
int
mu_dbm_fetch (DBM_FILE db, DBM_DATUM key, DBM_DATUM *ret)
{
*ret = gdbm_fetch (db, key);
return ret->dptr == NULL;
}
int
mu_dbm_delete (DBM_FILE db, DBM_DATUM key)
{
return gdbm_delete (db, key);
}
int
mu_dbm_insert (DBM_FILE db, DBM_DATUM key, DBM_DATUM contents, int replace)
{
return gdbm_store (db, key, contents,
replace ? GDBM_REPLACE : GDBM_INSERT);
}
DBM_DATUM
mu_dbm_firstkey (DBM_FILE db)
{
return gdbm_firstkey (db);
}
DBM_DATUM
mu_dbm_nextkey (DBM_FILE db, DBM_DATUM key)
{
return gdbm_nextkey (db, key);
}
void
mu_dbm_datum_free (DBM_DATUM *datum)
{
void *ptr = MU_DATUM_PTR (*datum);
if (ptr)
free (ptr);
MU_DATUM_PTR (*datum) = 0;
}
#elif defined(WITH_BDB)
#define DB_SUFFIX ".db"
int
mu_dbm_stat (char *name, struct stat *sb)
{
int rc;
char *pfname = make_db_name (name, DB_SUFFIX);
rc = stat (pfname, sb);
free (pfname);
return rc;
}
int
mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode)
{
int f, rc;
DB *db;
char *pfname = make_db_name (name, DB_SUFFIX);
if (mu_check_perm (pfname, mode))
{
free (pfname);
errno = MU_ERR_UNSAFE_PERMS;
return -1;
}
switch (flags)
{
case MU_STREAM_CREAT:
f = DB_CREATE|DB_TRUNCATE;
break;
case MU_STREAM_READ:
f = DB_RDONLY;
break;
case MU_STREAM_RDWR:
f = DB_CREATE;
break;
default:
free (pfname);
errno = EINVAL;
return -1;
}
#if WITH_BDB == 2
rc = db_open (pfname, DB_HASH, f, mode, NULL, NULL, &db);
#else
rc = db_create (&db, NULL, 0);
if (rc != 0 || db == NULL)
return rc;
# if DB_VERSION_MAJOR == 3
rc = db->open (db, pfname, NULL, DB_HASH, f, mode);
# else
rc = db->open (db, NULL, pfname, NULL, DB_HASH, f, mode);
# endif
#endif
free (pfname);
if (rc)
return -1;
*dbm = malloc (sizeof **dbm);
if (!*dbm)
{
db->close (db, 0);
errno = ENOMEM;
return -1;
}
(*dbm)->db = db;
(*dbm)->dbc = NULL;
return 0;
}
int
mu_dbm_close (DBM_FILE db)
{
db->db->close (db->db, 0);
free (db);
return 0;
}
int
mu_dbm_fetch (DBM_FILE db, DBM_DATUM key, DBM_DATUM *ret)
{
return db->db->get (db->db, NULL, &key, ret, 0);
}
int
mu_dbm_delete (DBM_FILE db, DBM_DATUM key)
{
return db->db->del (db->db, NULL, &key, 0);
}
int
mu_dbm_insert (DBM_FILE db, DBM_DATUM key, DBM_DATUM contents, int replace)
{
/*FIXME: replace unused*/
return db->db->put (db->db, NULL, &key, &contents, 0);
}
DBM_DATUM
mu_dbm_firstkey (DBM_FILE db)
{
DBT key, data;
int ret;
memset (&key, 0, sizeof key);
memset (&data, 0, sizeof data);
if (!db->dbc)
{
if (db->db->cursor (db->db, NULL, &db->dbc BDB2_CURSOR_LASTARG) != 0)
return key;
}
if ((ret = db->dbc->c_get (db->dbc, &key, &data, DB_FIRST)) != 0)
{
key.data = NULL;
key.size = 0;
if (ret == DB_NOTFOUND)
errno = MU_ERR_NOENT;
else
errno = ret;
}
return key;
}
DBM_DATUM
mu_dbm_nextkey (DBM_FILE db, DBM_DATUM pkey /*unused*/)
{
DBT key, data;
int ret;
memset (&key, 0, sizeof key);
memset (&data, 0, sizeof data);
if (!db->dbc)
return key;
if ((ret = db->dbc->c_get (db->dbc, &key, &data, DB_NEXT)) != 0)
{
key.data = NULL;
key.size = 0;
if (ret == DB_NOTFOUND)
errno = MU_ERR_NOENT;
else
errno = ret;
}
return key;
}
void
mu_dbm_datum_free (DBM_DATUM *datum)
{
/* empty */
}
#elif defined(WITH_NDBM)
#define DB_SUFFIX ".pag"
int
mu_dbm_stat (char *name, struct stat *sb)
{
int rc;
char *pfname = make_db_name (name, DB_SUFFIX);
rc = stat (pfname, sb);
free (pfname);
return rc;
}
int
mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode)
{
int f;
char *pfname;
switch (flags)
{
case MU_STREAM_CREAT:
f = O_CREAT|O_TRUNC|O_RDWR;
break;
case MU_STREAM_READ:
f = O_RDONLY;
break;
case MU_STREAM_RDWR:
f = O_CREAT|O_RDWR;
break;
default:
errno = EINVAL;
return -1;
}
pfname = strip_suffix (name, DB_SUFFIX);
*db = dbm_open (pfname, f, mode);
free (pfname);
if (!*db)
return -1;
if (mu_fcheck_perm (dbm_dirfno (*db), mode)
|| mu_fcheck_perm (dbm_pagfno (*db), mode))
{
dbm_close (*db);
return 1;
}
return 0;
}
int
mu_dbm_close (DBM_FILE db)
{
dbm_close (db);
return 0;
}
int
mu_dbm_fetch (DBM_FILE db, DBM_DATUM key, DBM_DATUM *ret)
{
*ret = dbm_fetch (db, key);
return ret->dptr == NULL;
}
int
mu_dbm_delete (DBM_FILE db, DBM_DATUM key)
{
return dbm_delete (db, key);
}
int
mu_dbm_insert (DBM_FILE db, DBM_DATUM key, DBM_DATUM contents, int replace)
{
return dbm_store (db, key, contents, replace ? DBM_REPLACE : DBM_INSERT);
}
DBM_DATUM
mu_dbm_firstkey (DBM_FILE db)
{
return dbm_firstkey (db);
}
DBM_DATUM
mu_dbm_nextkey (DBM_FILE db, DBM_DATUM key)
{
return dbm_nextkey (db, key);
}
void
mu_dbm_datum_free (DBM_DATUM *datum)
{
/* empty */
}
#elif defined(WITH_TOKYOCABINET)
#define DB_SUFFIX ".tch"
int
mu_dbm_stat (char *name, struct stat *sb)
{
int rc;
char *pfname = make_db_name (name, DB_SUFFIX);
rc = stat (pfname, sb);
free (pfname);
return rc;
}
int
mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode)
{
int f, ecode;
char *pfname = make_db_name (name, DB_SUFFIX);
if (mu_check_perm (pfname, mode))
{
free (pfname);
return -1;
}
switch (flags)
{
case MU_STREAM_CREAT:
f = HDBOWRITER | HDBOCREAT;
break;
case MU_STREAM_READ:
f = HDBOREADER;
break;
case MU_STREAM_RDWR:
f = HDBOREADER | HDBOWRITER;
break;
default:
free (pfname);
errno = EINVAL;
return 1;
}
*db = malloc (sizeof **db);
if (!*db)
{
errno = ENOMEM;
return -1;
}
(*db)->hdb = tchdbnew ();
if (!tchdbopen ((*db)->hdb, pfname, f))
ecode = tchdbecode ((*db)->hdb);
free (pfname);
return 0;
}
int
mu_dbm_close (DBM_FILE db)
{
tchdbclose (db->hdb);
tchdbdel (db->hdb);
return 0;
}
int
mu_dbm_fetch (DBM_FILE db, DBM_DATUM key, DBM_DATUM *ret)
{
ret->data = tchdbget (db->hdb, key.data, key.size, &ret->size);
return ret->data == NULL;
}
int
mu_dbm_delete (DBM_FILE db, DBM_DATUM key)
{
return !tchdbout (db->hdb, key.data, key.size);
}
int
mu_dbm_insert (DBM_FILE db, DBM_DATUM key, DBM_DATUM contents, int replace)
{
if (replace)
return !tchdbput (db->hdb, key.data, key.size, contents.data, contents.size);
else
return !tchdbputkeep (db->hdb, key.data, key.size,
contents.data, contents.size);
}
DBM_DATUM
mu_dbm_firstkey (DBM_FILE db)
{
DBM_DATUM key;
memset (&key, 0, sizeof key);
tchdbiterinit (db->hdb);
key.data = tchdbiternext (db->hdb, &key.size);
return key;
}
DBM_DATUM
mu_dbm_nextkey (DBM_FILE db, DBM_DATUM unused)
{
DBM_DATUM key;
memset (&key, 0, sizeof key);
key.data = tchdbiternext (db->hdb, &key.size);
return key;
}
void
mu_dbm_datum_free (DBM_DATUM *datum)
{
/* empty */
}
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2000, 2001, 2002, 2005, 2007, 2009, 2010, 2011
Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#if defined(WITH_GDBM)
#include <gdbm.h>
#define USE_DBM
typedef GDBM_FILE DBM_FILE;
typedef datum DBM_DATUM;
#define MU_DATUM_SIZE(d) (d).dsize
#define MU_DATUM_PTR(d) (d).dptr
#elif defined(WITH_BDB)
#include <db.h>
#define USE_DBM
struct db2_file
{
DB *db;
DBC *dbc;
};
typedef struct db2_file *DBM_FILE;
typedef DBT DBM_DATUM;
#define MU_DATUM_SIZE(d) (d).size
#define MU_DATUM_PTR(d) (d).data
#elif defined(WITH_NDBM)
#include <ndbm.h>
#define USE_DBM
typedef DBM *DBM_FILE;
typedef datum DBM_DATUM;
#define MU_DATUM_SIZE(d) (d).dsize
#define MU_DATUM_PTR(d) (d).dptr
#elif defined(WITH_TOKYOCABINET)
#include <tcutil.h>
#include <tchdb.h>
#define USE_DBM
struct tokyocabinet_file
{
TCHDB *hdb;
};
struct tokyocabinet_datum {
void *data;
int size;
};
typedef struct tokyocabinet_file *DBM_FILE;
typedef struct tokyocabinet_datum DBM_DATUM;
#define MU_DATUM_SIZE(d) (d).size
#define MU_DATUM_PTR(d) (d).data
#endif
#ifdef USE_DBM
struct stat;
int mu_dbm_stat (char *name, struct stat *sb);
int mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode);
int mu_dbm_close (DBM_FILE db);
int mu_dbm_fetch (DBM_FILE db, DBM_DATUM key, DBM_DATUM *ret);
int mu_dbm_insert (DBM_FILE db, DBM_DATUM key, DBM_DATUM contents, int replace);
int mu_dbm_delete (DBM_FILE db, DBM_DATUM key);
DBM_DATUM mu_dbm_firstkey (DBM_FILE db);
DBM_DATUM mu_dbm_nextkey (DBM_FILE db, DBM_DATUM key);
void mu_dbm_datum_free(DBM_DATUM *datum);
#endif /* USE_DBM */
int mu_fcheck_perm (int fd, int mode);
int mu_check_perm (const char *name, int mode);
......@@ -31,10 +31,10 @@ int mu_c_tab[MU_C_TAB_MAX] = {
MU_CTYPE_CNTRL,
MU_CTYPE_CNTRL,
MU_CTYPE_CNTRL|MU_CTYPE_SPACE,
MU_CTYPE_CNTRL|MU_CTYPE_SPACE|MU_CTYPE_ENDLN,
MU_CTYPE_CNTRL|MU_CTYPE_SPACE,
MU_CTYPE_CNTRL|MU_CTYPE_SPACE,
MU_CTYPE_CNTRL|MU_CTYPE_SPACE,
MU_CTYPE_CNTRL|MU_CTYPE_SPACE,
MU_CTYPE_CNTRL|MU_CTYPE_SPACE|MU_CTYPE_ENDLN,
MU_CTYPE_CNTRL,
MU_CTYPE_CNTRL,
MU_CTYPE_CNTRL,
......
## This file is part of GNU Mailutils.
## Copyright (C) 2011 Free Software Foundation, Inc.
##
## GNU Mailutils is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License as
## published by the Free Software Foundation; either version 3, or (at
## your option) any later version.
##
## GNU Mailutils is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
## General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
INCLUDES = @MU_LIB_COMMON_INCLUDES@ @DBMINCLUDES@
lib_LTLIBRARIES = libmu_dbm.la
libmu_dbm_la_SOURCES = \
close.c\
create.c\
datumfree.c\
dbm.c\
delete.c\
destroy.c\
errstr.c\
fetch.c\
firstkey.c\
getfd.c\
nextkey.c\
open.c\
safety.c\
store.c\
berkeley.c\
gdbm.c\
ndbm.c
noinst_HEADERS = mudbm.h
libmu_dbm_la_LIBADD = ${MU_LIB_MAILUTILS} @MU_AUTHLIBS@ @DBMLIBS@ @LTLIBINTL@
libmu_dbm_la_LDFLAGS = -version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
libmu_dbm_la_DEPENDENCIES = @DBMLIB_DEPENDENCY@
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/util.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/stream.h>
#include "mudbm.h"
#if defined(WITH_BDB)
#include <db.h>
struct bdb_file
{
DB *db;
DBC *dbc;
};
static int
_bdb_file_safety (mu_dbm_file_t db, int mode, uid_t owner)
{
return mu_file_safety_check (db->db_name, mode, owner, NULL);
}
static int
_bdb_get_fd (mu_dbm_file_t db, int *pag, int *dir)
{
struct bdb_file *bdb_file = db->db_descr;
int rc = bdb_file->db->fd (bdb_file->db, pag);
if (rc)
{
db->db_errno.n = rc;
return MU_ERR_FAILURE;
}
if (dir)
*dir = *pag;
return 0;
}
static int
_bdb_open (mu_dbm_file_t mdb, int flags, int mode)
{
struct bdb_file *bdb_file;
int f, rc;
DB *db;
switch (flags)
{
case MU_STREAM_CREAT:
f = DB_CREATE|DB_TRUNCATE;
break;
case MU_STREAM_READ:
f = DB_RDONLY;
break;
case MU_STREAM_RDWR:
f = DB_CREATE;
break;
default:
return EINVAL;
}
#if WITH_BDB == 2
rc = db_open (db->db_name, DB_HASH, f, mode, NULL, NULL, &db);
#else
rc = db_create (&db, NULL, 0);
if (rc != 0 || db == NULL)
return MU_ERR_FAILURE;
# if DB_VERSION_MAJOR == 3
rc = db->open (db, mdb->db_name, NULL, DB_HASH, f, mode);
# else
rc = db->open (db, NULL, mdb->db_name, NULL, DB_HASH, f, mode);
# endif
#endif
if (rc)
return MU_ERR_FAILURE;
bdb_file = malloc (sizeof *bdb_file);
if (!bdb_file)
{
db->close (db, 0);
return ENOMEM;
}
bdb_file->db = db;
bdb_file->dbc = NULL;
mdb->db_descr = bdb_file;
return 0;
}
static int
_bdb_close (mu_dbm_file_t db)
{
if (db->db_descr)
{
struct bdb_file *bdb_file = db->db_descr;
bdb_file->db->close (bdb_file->db, 0);
free (bdb_file);
db->db_descr = NULL;
}
return 0;
}
static int
_bdb_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
struct mu_dbm_datum *ret)
{
DBT keydat, content;
struct bdb_file *bdb_file = db->db_descr;
int rc;
memset (&keydat, 0, sizeof keydat);
keydat.data = key->mu_dptr;
keydat.size = key->mu_dsize;
memset (&content, 0, sizeof content);
content.flags = DB_DBT_MALLOC;
rc = bdb_file->db->get (bdb_file->db, NULL, &keydat, &content, 0);
mu_dbm_datum_free (ret);
switch (rc)
{
case 0:
ret->mu_dptr = content.data;
ret->mu_dsize = content.size;
ret->mu_sys = db->db_sys;
break;
case DB_NOTFOUND:
db->db_errno.n = rc;
rc = MU_ERR_NOENT;
break;
default:
db->db_errno.n = rc;
rc = MU_ERR_FAILURE;
}
return rc;
}
static int
_bdb_store (mu_dbm_file_t db,
struct mu_dbm_datum const *key,
struct mu_dbm_datum const *contents,
int replace)
{
struct bdb_file *bdb_file = db->db_descr;
int rc;
DBT keydat, condat;
memset (&keydat, 0, sizeof keydat);
keydat.data = key->mu_dptr;
keydat.size = key->mu_dsize;
memset (&condat, 0, sizeof condat);
condat.data = contents->mu_dptr;
condat.size = contents->mu_dsize;
rc = bdb_file->db->put (bdb_file->db, NULL, &keydat, &condat,
replace ? 0 : DB_NOOVERWRITE);
db->db_errno.n = rc;
switch (rc)
{
case 0:
break;
case DB_KEYEXIST:
rc = MU_ERR_EXISTS;
break;
default:
rc = MU_ERR_FAILURE;
break;
}
return rc;
}
static int
_bdb_delete (mu_dbm_file_t db, struct mu_dbm_datum const *key)
{
DBT keydat;
struct bdb_file *bdb_file = db->db_descr;
int rc;
memset (&keydat, 0, sizeof keydat);
keydat.data = key->mu_dptr;
keydat.size = key->mu_dsize;
rc = bdb_file->db->del (bdb_file->db, NULL, &keydat, 0);
switch (rc)
{
case 0:
break;
case DB_NOTFOUND:
db->db_errno.n = rc;
rc = MU_ERR_NOENT;
break;
default:
db->db_errno.n = rc;
rc = MU_ERR_FAILURE;
}
return rc;
}
static int
_bdb_firstkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
{
struct bdb_file *bdb_file = db->db_descr;
int rc;
DBT key, dbt;
if (!bdb_file->dbc)
{
rc = bdb_file->db->cursor (bdb_file->db, NULL, &bdb_file->dbc
BDB2_CURSOR_LASTARG);
if (rc)
{
db->db_errno.n = rc;
return MU_ERR_FAILURE;
}
}
memset (&key, 0, sizeof key);
key.flags = DB_DBT_MALLOC;
memset (&dbt, 0, sizeof dbt);
dbt.flags = DB_DBT_MALLOC;
rc = bdb_file->dbc->c_get (bdb_file->dbc, &key, &dbt, DB_FIRST);
mu_dbm_datum_free (ret);
switch (rc)
{
case 0:
free (dbt.data); /* FIXME: cache it for the eventual fetch that can
follow */
ret->mu_dptr = key.data;
ret->mu_dsize = key.size;
ret->mu_sys = db->db_sys;
break;
case DB_NOTFOUND:
db->db_errno.n = rc;
rc = MU_ERR_NOENT;
break;
default:
db->db_errno.n = rc;
rc = MU_ERR_FAILURE;
}
return rc;
}
static int
_bdb_nextkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
{
struct bdb_file *bdb_file = db->db_descr;
int rc;
DBT key, dbt;
if (!bdb_file->dbc)
return MU_ERR_SEQ;
memset (&key, 0, sizeof key);
key.flags = DB_DBT_MALLOC;
memset (&dbt, 0, sizeof dbt);
dbt.flags = DB_DBT_MALLOC;
rc = bdb_file->dbc->c_get (bdb_file->dbc, &key, &dbt, DB_NEXT);
mu_dbm_datum_free (ret);
switch (rc)
{
case 0:
free (dbt.data); /* FIXME: cache it for the eventual fetch that can
follow */
ret->mu_dptr = key.data;
ret->mu_dsize = key.size;
ret->mu_sys = db->db_sys;
break;
case DB_NOTFOUND:
db->db_errno.n = rc;
rc = MU_ERR_NOENT;
break;
default:
db->db_errno.n = rc;
rc = MU_ERR_FAILURE;
}
return rc;
}
static void
_bdb_datum_free (struct mu_dbm_datum *datum)
{
free (datum->mu_dptr);
}
static char const *
_bdb_strerror (mu_dbm_file_t db)
{
return db_strerror (db->db_errno.n);
}
struct mu_dbm_impl _mu_dbm_bdb = {
"bdb",
_bdb_file_safety,
_bdb_get_fd,
_bdb_open,
_bdb_close,
_bdb_fetch,
_bdb_store,
_bdb_delete,
_bdb_firstkey,
_bdb_nextkey,
_bdb_datum_free,
_bdb_strerror
};
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
int
mu_dbm_close (mu_dbm_file_t db)
{
DBMSYSCK (db, _dbm_close);
if (!db->db_descr)
return 0;
return db->db_sys->_dbm_close (db);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011
Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <unistd.h>
#include <stdlib.h>
#include <mailutils/types.h>
#include <mailutils/list.h>
#include <mailutils/url.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include <mailutils/util.h>
#include "mudbm.h"
int
mu_dbm_create (char *name, mu_dbm_file_t *db)
{
int rc;
mu_url_t url;
_mu_dbm_init ();
rc = mu_url_create_hint (&url, name, 0, mu_dbm_hint);
if (rc)
return rc;
rc = mu_dbm_create_from_url (url, db);
mu_url_destroy (&url);
return rc;
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
void
mu_dbm_datum_free (struct mu_dbm_datum *datum)
{
if (datum && datum->mu_data &&
datum->mu_sys && datum->mu_sys->_dbm_datum_free)
{
datum->mu_sys->_dbm_datum_free (datum);
datum->mu_data = NULL;
}
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <mailutils/types.h>
#include <mailutils/list.h>
#include <mailutils/url.h>
#include <mailutils/dbm.h>
#include <mailutils/util.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/nls.h>
#include <mailutils/mu_auth.h>
#include "mudbm.h"
static mu_list_t implist;
mu_url_t mu_dbm_hint;
static void
_implist_free (void *p)
{
struct mu_dbm_impl *impl = p;
free (impl->_dbm_name);
free (impl);
}
static int
_implist_cmp (const void *a, const void *b)
{
struct mu_dbm_impl const *ia = a;
struct mu_dbm_impl const *ib = b;
return strcmp (ia->_dbm_name, ib->_dbm_name);
}
void
_mu_dbm_init ()
{
int rc;
if (implist)
return;
rc = mu_list_create (&implist);
if (rc)
{
mu_error (_("cannot initialize DBM subsystem: %s"),
mu_strerror (rc));
abort ();
}
mu_list_set_destroy_item (implist, _implist_free);
mu_list_set_comparator (implist, _implist_cmp);
/* Add built-in entries */
#ifdef WITH_GDBM
mu_dbm_register (&_mu_dbm_gdbm);
#endif
#ifdef WITH_BDB
mu_dbm_register (&_mu_dbm_bdb);
#endif
#ifdef WITH_NDBM
mu_dbm_register (&_mu_dbm_ndbm);
#endif
#ifdef WITH_TOKYOCABINET
mu_dbm_register (&_mu_dbm_tokyokabinet);
#endif
if (!mu_dbm_hint)
{
struct mu_dbm_impl *impl;
char *urlbuf;
rc = mu_list_get (implist, 0, (void**) &impl);
if (rc)
{
mu_error (_("cannot initialize DBM hint: %s"),
mu_strerror (rc));
abort ();
}
urlbuf = malloc (strlen (impl->_dbm_name) + 4);
if (urlbuf)
{
strcpy (urlbuf, impl->_dbm_name);
strcat (urlbuf, "://");
rc = mu_url_create (&mu_dbm_hint, urlbuf);
free (urlbuf);
}
else
rc = ENOMEM;
if (rc)
{
mu_error (_("cannot initialize DBM hint: %s"),
mu_strerror (rc));
abort ();
}
}
}
int
mu_dbm_register (struct mu_dbm_impl *impl)
{
int rc;
struct mu_dbm_impl *ptr;
_mu_dbm_init ();
ptr = calloc (1, sizeof (*ptr));
if (!ptr)
return ENOMEM;
*ptr = *impl;
ptr->_dbm_name = strdup (impl->_dbm_name);
if (!ptr->_dbm_name)
{
free (ptr);
return ENOMEM;
}
rc = mu_list_append (implist, ptr);
if (rc)
_implist_free (ptr);
return rc;
}
int
mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db)
{
mu_dbm_file_t p;
int flags;
int rc;
const char *db_name;
struct mu_dbm_impl impl_key;
struct mu_dbm_impl *impl;
struct mu_auth_data *auth;
int safety_flags = 0;
uid_t owner_uid = getuid ();
_mu_dbm_init ();
mu_url_get_flags (url, &flags);
if ((flags & (MU_URL_HOST | MU_URL_PATH)) == (MU_URL_HOST | MU_URL_PATH))
return MU_ERR_URL_EXTRA_PARTS;
if (flags & MU_URL_HOST)
rc = mu_url_sget_host (url, &db_name);
else
rc = mu_url_sget_path (url, &db_name);
if (rc)
return rc;
rc = mu_url_sget_scheme (url, (const char**)&impl_key._dbm_name);
if (rc)
return rc;
rc = mu_list_locate (implist, (void *) &impl_key, (void **) &impl);
if (rc)
return rc;
if (flags & MU_URL_PARAM)
{
size_t fvc, i;
char **fvp;
mu_url_sget_fvpairs (url, &fvc, &fvp);
for (i = 0; i < fvc; i++)
{
const char *name = fvp[i];
int negate = 0;
int val;
if (*name == '-')
{
negate = 1;
name++;
}
else if (*name == '+')
name++;
if (strncmp (name, "owner", 5) == 0)
{
val = MU_FILE_SAFETY_OWNER_MISMATCH;
if (name[5] == '=')
{
auth = mu_get_auth_by_name (name + 6);
if (!auth)
{
char *end;
unsigned long uid;
errno = 0;
uid = strtoul (name + 6, &end, 0);
if (*end || errno)
return MU_ERR_NO_SUCH_USER;
auth = mu_get_auth_by_uid (uid);
if (!auth)
return MU_ERR_NO_SUCH_USER;
owner_uid = auth->uid;
mu_auth_data_free (auth);
}
}
else if (name[5])
return MU_ERR_URL_EXTRA_PARTS;//FIXME: better error code
}
else if (strcmp (name, "none") == 0)
{
safety_flags = negate ? MU_FILE_SAFETY_ALL : MU_FILE_SAFETY_NONE;
continue;
}
else if (strcmp (name, "all") == 0)
{
safety_flags = negate ? MU_FILE_SAFETY_NONE : MU_FILE_SAFETY_ALL;
continue;
}
else if (strcmp (name, "default") == 0)
{
val = DEFAULT_DBM_SAFETY_FLAGS;
}
else if (mu_file_safety_name_to_code (name, &val))
return MU_ERR_URL_EXTRA_PARTS;//FIXME: better error code
if (negate)
safety_flags &= ~val;
else
safety_flags |= val;
}
}
p = calloc (1, sizeof (*p));
if (!p)
return ENOMEM;
p->db_name = strdup (db_name);
if (!p->db_name)
{
free (p);
return ENOMEM;
}
p->db_safety_flags = safety_flags;
p->db_owner = owner_uid;
p->db_sys = impl;
*db = p;
return 0;
}
int
mu_dbm_impl_iterator (mu_iterator_t *itr)
{
_mu_dbm_init ();
return mu_list_get_iterator (implist, itr);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
int
mu_dbm_delete (mu_dbm_file_t db, struct mu_dbm_datum const *key)
{
DBMSYSCK (db, _dbm_delete);
if (!db->db_descr)
return EINVAL;
return db->db_sys->_dbm_delete (db, key);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
void
mu_dbm_destroy (mu_dbm_file_t *pdb)
{
if (pdb && *pdb)
{
mu_dbm_file_t db = *pdb;
if (db->db_descr)
mu_dbm_close (db);
free (db->db_name);
free (db);
*pdb = NULL;
}
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
char const *
mu_dbm_strerror (mu_dbm_file_t db)
{
if (!db)
return NULL;
if (!db->db_sys || !db->db_sys->_dbm_strerror)
return NULL;
if (!db->db_descr)
return mu_strerror (MU_ERR_NOT_OPEN);
return db->db_sys->_dbm_strerror (db);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
int
mu_dbm_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
struct mu_dbm_datum *ret)
{
DBMSYSCK (db, _dbm_fetch);
if (!db->db_descr)
return EINVAL;
return db->db_sys->_dbm_fetch (db, key, ret);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
int
mu_dbm_firstkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
{
DBMSYSCK (db, _dbm_firstkey);
if (!db->db_descr)
return EINVAL;
return db->db_sys->_dbm_firstkey (db, ret);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/util.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/stream.h>
#include "mudbm.h"
#if defined(WITH_GDBM)
#include <gdbm.h>
struct gdbm_descr
{
GDBM_FILE file; /* GDBM file */
datum prev; /* Previous key for sequential access */
};
static int
_gdbm_file_safety (mu_dbm_file_t db, int mode, uid_t owner)
{
return mu_file_safety_check (db->db_name, mode, owner, NULL);
}
int
_gdbm_get_fd (mu_dbm_file_t db, int *pag, int *dir)
{
struct gdbm_descr *gd = db->db_descr;
*pag = gdbm_fdesc (gd->file);
if (dir)
*dir = *pag;
return 0;
}
static int
_gdbm_open (mu_dbm_file_t db, int flags, int mode)
{
int f;
struct gdbm_descr *gd;
GDBM_FILE file;
switch (flags)
{
case MU_STREAM_CREAT:
f = GDBM_NEWDB;
break;
case MU_STREAM_READ:
f = GDBM_READER;
break;
case MU_STREAM_RDWR:
f = GDBM_WRCREAT;
break;
default:
return EINVAL;
}
file = gdbm_open (db->db_name, 512, f, mode, NULL);
if (!file)
return MU_ERR_FAILURE;
gd = calloc (1, sizeof (*gd));
gd->file = file;
db->db_descr = gd;
return 0;
}
static int
_gdbm_close (mu_dbm_file_t db)
{
if (db->db_descr)
{
struct gdbm_descr *gd = db->db_descr;
gdbm_close (gd->file);
free (gd);
db->db_descr = NULL;
}
return 0;
}
static int
_gdbm_conv_datum (mu_dbm_file_t db, struct mu_dbm_datum *ret, datum content,
int copy)
{
if (copy)
{
ret->mu_dptr = malloc (content.dsize);
if (!ret->mu_dptr)
return errno;
memcpy (ret->mu_dptr, content.dptr, content.dsize);
}
else
{
ret->mu_dptr = content.dptr;
}
ret->mu_dsize = content.dsize;
ret->mu_sys = db->db_sys;
return 0;
}
static int
_gdbm_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
struct mu_dbm_datum *ret)
{
struct gdbm_descr *gd = db->db_descr;
int rc;
datum keydat, content;
keydat.dptr = key->mu_dptr;
keydat.dsize = key->mu_dsize;
gdbm_errno = 0;
content = gdbm_fetch (gd->file, keydat);
if (content.dptr == NULL)
{
if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
return MU_ERR_NOENT;
else
{
db->db_errno.n = gdbm_errno;
return MU_ERR_FAILURE;
}
}
mu_dbm_datum_free (ret);
rc = _gdbm_conv_datum (db, ret, content, 1);
if (rc)
{
free (content.dptr);
return rc;
}
return 0;
}
static int
_gdbm_store (mu_dbm_file_t db,
struct mu_dbm_datum const *key,
struct mu_dbm_datum const *contents,
int replace)
{
struct gdbm_descr *gd = db->db_descr;
datum keydat, condat;
keydat.dptr = key->mu_dptr;
keydat.dsize = key->mu_dsize;
condat.dptr = contents->mu_dptr;
condat.dsize = contents->mu_dsize;
switch (gdbm_store (gd->file, keydat, condat, replace))
{
case 0:
break;
case 1:
return MU_ERR_EXISTS;
case -1:
db->db_errno.n = gdbm_errno;
return MU_ERR_FAILURE;
}
return 0;
}
static int
_gdbm_delete (mu_dbm_file_t db, struct mu_dbm_datum const *key)
{
struct gdbm_descr *gd = db->db_descr;
datum keydat;
keydat.dptr = key->mu_dptr;
keydat.dsize = key->mu_dsize;
gdbm_errno = 0;
if (gdbm_delete (gd->file, keydat))
{
if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
return MU_ERR_NOENT;
else
{
db->db_errno.n = gdbm_errno;
return MU_ERR_FAILURE;
}
}
return 0;
}
static int
_gdbm_firstkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
{
struct gdbm_descr *gd = db->db_descr;
int rc;
datum key = gdbm_firstkey (gd->file);
if (key.dptr == NULL)
{
if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
return MU_ERR_NOENT;
else
{
db->db_errno.n = gdbm_errno;
return MU_ERR_FAILURE;
}
}
mu_dbm_datum_free (ret);
rc = _gdbm_conv_datum (db, ret, key, 0);
if (rc)
{
free (key.dptr);
return rc;
}
free (gd->prev.dptr);
gd->prev = key;
return 0;
}
static int
_gdbm_nextkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
{
struct gdbm_descr *gd = db->db_descr;
int rc;
datum key;
if (!gd->prev.dptr)
return MU_ERR_NOENT;
key = gdbm_nextkey (gd->file, gd->prev);
if (key.dptr == NULL)
{
if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
return MU_ERR_NOENT;
else
{
db->db_errno.n = gdbm_errno;
return MU_ERR_FAILURE;
}
}
mu_dbm_datum_free (ret);
rc = _gdbm_conv_datum (db, ret, key, 0);
if (rc)
{
free (key.dptr);
return rc;
}
free (gd->prev.dptr);
gd->prev = key;
return 0;
}
static void
_gdbm_datum_free (struct mu_dbm_datum *datum)
{
free (datum->mu_dptr);
}
static char const *
_gdbm_strerror (mu_dbm_file_t db)
{
return gdbm_strerror (db->db_errno.n);
}
struct mu_dbm_impl _mu_dbm_gdbm = {
"gdbm",
_gdbm_file_safety,
_gdbm_get_fd,
_gdbm_open,
_gdbm_close,
_gdbm_fetch,
_gdbm_store,
_gdbm_delete,
_gdbm_firstkey,
_gdbm_nextkey,
_gdbm_datum_free,
_gdbm_strerror
};
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
int
mu_dbm_get_fd (mu_dbm_file_t db, int *pag, int *dir)
{
DBMSYSCK (db, _dbm_get_fd);
if (!db->db_descr || !pag)
return EINVAL;
return db->db_sys->_dbm_get_fd (db, pag, dir);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#include <mailutils/sys/dbm.h>
#define DBMSYSCK(db,meth) do \
{ \
if (!(db)) \
return EINVAL; \
if (!(db)->db_descr) \
return MU_ERR_NOT_OPEN; \
if (!(db)->db_sys || !(db)->db_sys->meth) \
return ENOSYS; \
} \
while (0)
#define DEFAULT_DBM_SAFETY_FLAGS MU_FILE_SAFETY_ALL
#ifdef WITH_GDBM
extern struct mu_dbm_impl _mu_dbm_gdbm;
#endif
#ifdef WITH_BDB
extern struct mu_dbm_impl _mu_dbm_bdb;
#endif
#ifdef WITH_NDBM
extern struct mu_dbm_impl _mu_dbm_ndbm;
#endif
#ifdef WITH_TOKYOCABINET
extern struct mu_dbm_impl _mu_dbm_tokyokabinet;
#endif
void _mu_dbm_init (void);
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/util.h>
#include <mailutils/errno.h>
#include <mailutils/error.h>
#include <mailutils/stream.h>
#include <mailutils/io.h>
#include "mudbm.h"
#if defined(WITH_NDBM)
#include <ndbm.h>
static int
_ndbm_file_safety (mu_dbm_file_t db, int mode, uid_t owner)
{
int rc;
char *name;
rc = mu_asprintf (&name, "%s.pag", db->db_name);
if (rc)
return rc;
rc = mu_file_safety_check (name, mode, owner, NULL);
if (rc)
{
free (name);
return rc;
}
strcpy (name + strlen (name) - 3, "dir");
rc = mu_file_safety_check (name, mode, owner, NULL);
free (name);
return rc;
}
int
_ndbm_get_fd (mu_dbm_file_t db, int *pag, int *dir)
{
DBM *dbm = db->db_descr;
*pag = dbm_pagfno (dbm);
if (dir)
*dir = dbm_dirfno (dbm);
return 0;
}
static int
_ndbm_open (mu_dbm_file_t db, int flags, int mode)
{
int f;
DBM *dbm;
switch (flags)
{
case MU_STREAM_CREAT:
f = O_CREAT|O_TRUNC|O_RDWR;
break;
case MU_STREAM_READ:
f = O_RDONLY;
break;
case MU_STREAM_RDWR:
f = O_CREAT|O_RDWR;
break;
default:
errno = EINVAL;
return -1;
}
dbm = dbm_open (db->db_name, f, mode);
if (!dbm)
return MU_ERR_FAILURE;
db->db_descr = dbm;
return 0;
}
static int
_ndbm_close (mu_dbm_file_t db)
{
if (db->db_descr)
{
dbm_close ((DBM *) db->db_descr);
db->db_descr = NULL;
}
return 0;
}
static int
_ndbm_conv_datum (mu_dbm_file_t db, struct mu_dbm_datum *ret, datum content)
{
ret->mu_dptr = malloc (content.dsize);
if (!ret->mu_dptr)
return errno;
memcpy (ret->mu_dptr, content.dptr, content.dsize);
ret->mu_dsize = content.dsize;
ret->mu_sys = db->db_sys;
return 0;
}
static int
_ndbm_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
struct mu_dbm_datum *ret)
{
datum keydat, content;
keydat.dptr = key->mu_dptr;
keydat.dsize = key->mu_dsize;
errno = 0;
content = dbm_fetch (db->db_descr, keydat);
mu_dbm_datum_free (ret);
if (content.dptr == NULL)
return MU_ERR_NOENT;
return _ndbm_conv_datum (db, ret, content);
}
static int
_ndbm_store (mu_dbm_file_t db,
struct mu_dbm_datum const *key,
struct mu_dbm_datum const *contents,
int replace)
{
DBM *dbm = db->db_descr;
datum keydat, condat;
keydat.dptr = key->mu_dptr;
keydat.dsize = key->mu_dsize;
condat.dptr = contents->mu_dptr;
condat.dsize = contents->mu_dsize;
errno = 0;
switch (dbm_store (dbm, keydat, condat,
replace ? DBM_REPLACE : DBM_INSERT))
{
case 0:
break;
case 1:
return MU_ERR_EXISTS;
case -1:
db->db_errno.n = errno;
return MU_ERR_FAILURE;
}
return 0;
}
static int
_ndbm_delete (mu_dbm_file_t db, struct mu_dbm_datum const *key)
{
DBM *dbm = db->db_descr;
datum keydat;
keydat.dptr = key->mu_dptr;
keydat.dsize = key->mu_dsize;
errno = 0;
switch (dbm_delete (dbm, keydat))
{
case 0:
break;
case 1:
return MU_ERR_NOENT;
case -1:
db->db_errno.n = errno;
return MU_ERR_FAILURE;
}
return 0;
}
static int
_ndbm_firstkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
{
DBM *dbm = db->db_descr;
datum keydat;
errno = 0;
keydat = dbm_firstkey (dbm);
if (keydat.dptr == NULL)
return MU_ERR_NOENT;
return _ndbm_conv_datum (db, ret, keydat);
}
static int
_ndbm_nextkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
{
DBM *dbm = db->db_descr;
datum keydat;
keydat = dbm_nextkey (dbm);
if (keydat.dptr == NULL)
return MU_ERR_NOENT;
return _ndbm_conv_datum (db, ret, keydat);
}
static void
_ndbm_datum_free (struct mu_dbm_datum *datum)
{
free (datum->mu_dptr);
}
static char const *
_ndbm_strerror (mu_dbm_file_t db)
{
return strerror (db->db_errno.n);
}
struct mu_dbm_impl _mu_dbm_ndbm = {
"ndbm",
_ndbm_file_safety,
_ndbm_get_fd,
_ndbm_open,
_ndbm_close,
_ndbm_fetch,
_ndbm_store,
_ndbm_delete,
_ndbm_firstkey,
_ndbm_nextkey,
_ndbm_datum_free,
_ndbm_strerror
};
#endif
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
int
mu_dbm_nextkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
{
DBMSYSCK (db, _dbm_nextkey);
if (!db->db_descr)
return EINVAL;
return db->db_sys->_dbm_nextkey (db, ret);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
int
mu_dbm_open (mu_dbm_file_t db, int flags, int mode)
{
if (!db)
return EINVAL;
if (!db->db_sys || !db->db_sys->_dbm_open)
return ENOSYS;
return db->db_sys->_dbm_open (db, flags, mode);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
int
mu_dbm_safety_set_owner (mu_dbm_file_t db, uid_t uid)
{
if (!db)
return EINVAL;
db->db_owner = uid;
return 0;
}
int
mu_dbm_safety_get_owner (mu_dbm_file_t db, uid_t *uid)
{
if (!db)
return EINVAL;
*uid = db->db_owner;
return 0;
}
int
mu_dbm_safety_set_flags (mu_dbm_file_t db, int flags)
{
if (!db)
return EINVAL;
db->db_safety_flags = flags;
return 0;
}
int
mu_dbm_safety_get_flags (mu_dbm_file_t db, int *flags)
{
if (!db)
return EINVAL;
*flags = db->db_safety_flags;
return 0;
}
int
mu_dbm_safety_check (mu_dbm_file_t db)
{
if (!db)
return EINVAL;
if (!db->db_sys || !db->db_sys->_dbm_file_safety)
return ENOSYS;
return db->db_sys->_dbm_file_safety (db, db->db_safety_flags,
db->db_owner);
}
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <mailutils/types.h>
#include <mailutils/dbm.h>
#include <mailutils/errno.h>
#include "mudbm.h"
int
mu_dbm_store (mu_dbm_file_t db, struct mu_dbm_datum const *key,
struct mu_dbm_datum const *contents, int replace)
{
DBMSYSCK (db, _dbm_store);
if (!db->db_descr)
return EINVAL;
return db->db_sys->_dbm_store (db, key, contents, replace);
}
......@@ -36,7 +36,6 @@
#include <string.h>
#include <signal.h>
#include <regex.h>
#include <mu_dbm.h>
#include <mailutils/sieve.h>
#include <mailutils/mu_auth.h>
......
......@@ -46,6 +46,8 @@ maidag_LDADD = \
@MU_AUTHLIBS@\
${MU_LIB_MAILUTILS} \
@MU_COMMON_LIBRARIES@\
../libmu_dbm/libmu_dbm.la\
@DBMLIBS@\
@TCPWRAP_LIBRARIES@
INCLUDES = -I${top_srcdir} @MU_APP_COMMON_INCLUDES@ @GUILE_INCLUDES@ \
......
......@@ -457,7 +457,7 @@ struct mu_cfg_param maidag_cfg_param[] = {
{ "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, 0, NULL,
N_("Indicate temporary failure if the recipient is over his mail quota.")
},
#ifdef USE_DBM
#ifdef ENABLE_DBM
{ "quota-db", mu_cfg_string, &quotadbname, 0, NULL,
N_("Name of DBM quota database file."),
N_("file") },
......
......@@ -86,10 +86,9 @@
#include <mailutils/server.h>
#include <mailutils/cctype.h>
#include <mailutils/io.h>
#include <mailutils/dbm.h>
#include <mu_dbm.h>
#if defined (USE_DBM) || defined (USE_SQL)
#if defined (ENABLE_DBM) || defined (USE_SQL)
# define USE_MAILBOX_QUOTAS 1
#endif
......
......@@ -64,12 +64,12 @@ fail_retrieve_quota (char *name, mu_off_t *quota)
return RETR_FAILURE;
}
#ifdef USE_DBM
#ifdef ENABLE_DBM
int
dbm_retrieve_quota (char *name, mu_off_t *quota)
{
DBM_FILE db;
DBM_DATUM named, contentd;
mu_dbm_file_t db;
struct mu_dbm_datum named, contentd;
char buffer[64];
int unlimited = 0;
int rc;
......@@ -77,51 +77,72 @@ dbm_retrieve_quota (char *name, mu_off_t *quota)
if (!quotadbname)
return RETR_FAILURE;
if (mu_dbm_open (quotadbname, &db, MU_STREAM_READ, 0600))
rc = mu_dbm_create (quotadbname, &db);
if (rc)
{
mu_error (_("unable to create quota db"));
return RETR_FAILURE;
}
rc = mu_dbm_safety_check (db);
if (rc && rc != ENOENT)
{
mu_error (_("cannot open file %s: %s"), quotadbname, mu_strerror (errno));
mu_error (_("quota db fails safety check: %s"),
mu_strerror (rc));
mu_dbm_destroy (&db);
return RETR_FAILURE;
}
rc = mu_dbm_open (db, MU_STREAM_READ, 0600);
if (rc)
{
mu_error (_("cannot open file %s: %s"),
quotadbname, mu_strerror (rc));
mu_dbm_destroy (&db);
return RETR_FAILURE;
}
memset (&named, 0, sizeof named);
memset (&contentd, 0, sizeof contentd);
MU_DATUM_PTR (named) = name;
MU_DATUM_SIZE (named) = strlen (name);
rc = mu_dbm_fetch (db, named, &contentd);
if (rc || !MU_DATUM_PTR (contentd))
named.mu_dptr = name;
named.mu_dsize = strlen (name);
rc = mu_dbm_fetch (db, &named, &contentd);
if (rc)
{
/* User not in database, try default quota */
memset (&named, 0, sizeof named);
MU_DATUM_PTR (named) = "DEFAULT";
MU_DATUM_SIZE (named) = strlen ("DEFAULT");
rc = mu_dbm_fetch (db, named, &contentd);
if (rc)
mu_dbm_datum_free (&named);
named.mu_dptr = "DEFAULT";
named.mu_dsize = strlen ("DEFAULT");
rc = mu_dbm_fetch (db, &named, &contentd);
if (rc == MU_ERR_NOENT)
{
/*mu_error (_("can't fetch data: %s"), strerror (rc));*/
mu_dbm_destroy (&db);
return RETR_FAILURE;
}
if (!MU_DATUM_PTR (contentd))
else if (rc)
{
mu_error (_("can't fetch data: %s"), mu_dbm_strerror (db));
mu_dbm_destroy (&db);
return RETR_FAILURE;
}
}
if (mu_c_strncasecmp("none",
MU_DATUM_PTR (contentd),
MU_DATUM_SIZE (contentd)) == 0)
if (mu_c_strncasecmp("none", contentd.mu_dptr, contentd.mu_dsize) == 0)
unlimited = 1;
else if (MU_DATUM_SIZE (contentd) > sizeof(buffer)-1)
else if (contentd.mu_dsize > sizeof (buffer) - 1)
{
mu_error (ngettext ("mailbox quota for `%s' is too big: %d digit",
"mailbox quota for `%s' is too big: %d digits",
MU_DATUM_SIZE (contentd)),
name, MU_DATUM_SIZE (contentd));
contentd.mu_dsize),
name, contentd.mu_dsize);
*quota = groupquota;
}
else
{
char *p;
strncpy(buffer, MU_DATUM_PTR (contentd), MU_DATUM_SIZE (contentd));
buffer[MU_DATUM_SIZE (contentd)] = 0;
strncpy (buffer, contentd.mu_dptr, contentd.mu_dsize);
buffer[contentd.mu_dsize] = 0;
*quota = strtoul (buffer, &p, 0);
if (get_size (buffer, quota, &p))
{
......@@ -130,7 +151,8 @@ dbm_retrieve_quota (char *name, mu_off_t *quota)
}
}
mu_dbm_close (db);
mu_dbm_datum_free (&contentd);
mu_dbm_destroy (&db);
return unlimited ? RETR_UNLIMITED : RETR_OK;
}
......
......@@ -32,9 +32,17 @@ else
IDLE_MODULES+=imap.c
endif
if MU_COND_DBM
DBM_C=dbm.c
LIBMU_DBM=../libmu_dbm/libmu_dbm.la
else
IDLE_MODULES+=dbm.c
endif
MODULES = \
acl.c\
cflags.c\
$(DBM_C)\
$(IMAP_C)\
filter.c\
flt2047.c\
......@@ -67,6 +75,7 @@ mu_LDADD = \
${MU_LIB_AUTH}\
@MU_AUTHLIBS@\
${MU_LIB_MAILUTILS}\
${LIBMU_DBM} @DBMLIBS@\
@READLINE_LIBS@ @MU_COMMON_LIBRARIES@
INCLUDES = @MU_APP_COMMON_INCLUDES@ @MU_AUTHINCS@
......@@ -77,7 +86,8 @@ AM_CPPFLAGS = \
-DAUTHLIBS="\"$(MU_AUTHLIBS)\"" \
-DGUILE_LIBS="\"$(GUILE_LIBS)\"" \
-DPYTHON_LIBS="\"$(PYTHON_LIBS)\"" \
-DI18NLIBS="\"$(LIBINTL)\""
-DI18NLIBS="\"$(LIBINTL)\"" \
-DDBMLIBS="\"$(DBMLIBS)\""
BUILT_SOURCES=mu-setup.c mu-setup.h
EXTRA_DIST=mu-setup.awk mu-setup.c mu-setup.h template.c
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010, 2011 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#if defined(HAVE_CONFIG_H)
# include <config.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <grp.h>
#include <sysexits.h>
#include <fnmatch.h>
#include <regex.h>
#include <mailutils/mailutils.h>
#include <mailutils/dbm.h>
#include "argp.h"
#include "mu.h"
#include "xalloc.h"
static char dbm_doc[] = N_("mu dbm - DBM management tool");
char dbm_docstring[] = N_("DBM management tool");
static char dbm_args_doc[] = N_("FILE [KEY...]");
enum mode
{
mode_list,
mode_create,
mode_delete,
mode_add,
mode_replace,
};
enum key_type
{
key_literal,
key_glob,
key_regex
};
enum mode mode;
char *db_name;
char *input_file;
int permissions = 0600;
struct mu_auth_data *auth;
uid_t owner_uid = -1;
gid_t owner_gid = -1;
int copy_permissions;
enum key_type key_type = key_literal;
int case_sensitive = 1;
int include_zero = -1;
void
init_datum (struct mu_dbm_datum *key, char *str)
{
memset (key, 0, sizeof *key);
key->mu_dptr = str;
key->mu_dsize = strlen (str) + !!include_zero;
}
mu_dbm_file_t
open_db_file (int mode)
{
int rc;
mu_dbm_file_t db;
rc = mu_dbm_create (db_name, &db);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR, _("unable to create database %s: %s"),
db_name, mu_strerror (rc));
exit (EX_SOFTWARE);
}
rc = mu_dbm_open (db, mode, permissions);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_dbm_open", db_name, rc);
exit (EX_SOFTWARE);
}
if (mode == MU_STREAM_CREAT && (owner_uid != -1 || owner_gid != -1))
{
int dirfd, pagfd;
rc = mu_dbm_get_fd (db, &pagfd, &dirfd);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_dbm_get_fd", db_name, rc);
exit (EX_SOFTWARE);
}
if (owner_uid == -1 || owner_gid == -1)
{
struct stat st;
if (fstat (dirfd, &st))
{
mu_diag_funcall (MU_DIAG_ERROR, "fstat", db_name, errno);
exit (EX_SOFTWARE);
}
if (owner_uid == -1)
owner_uid = st.st_uid;
if (owner_gid == -1)
owner_gid = st.st_gid;
}
if (fchown (pagfd, owner_uid, owner_gid))
{
mu_diag_funcall (MU_DIAG_ERROR, "fchown", db_name, errno);
exit (EX_SOFTWARE);
}
if (pagfd != dirfd &&
fchown (dirfd, owner_uid, owner_gid))
{
mu_diag_funcall (MU_DIAG_ERROR, "fchown", db_name, errno);
exit (EX_SOFTWARE);
}
}
return db;
}
struct print_data
{
mu_dbm_file_t db;
mu_stream_t stream;
};
static int
print_action (struct mu_dbm_datum const *key, void *data)
{
int rc;
struct mu_dbm_datum contents;
struct print_data *pd = data;
size_t len;
memset (&contents, 0, sizeof contents);
rc = mu_dbm_fetch (pd->db, key, &contents);
if (rc)
{
mu_error (_("database fetch error: %s"), mu_dbm_strerror (pd->db));
exit (EX_UNAVAILABLE);
}
len = key->mu_dsize;
if (key->mu_dptr[len - 1] == 0)
len--;
mu_stream_write (pd->stream, key->mu_dptr, len, NULL);
mu_stream_write (pd->stream, "\t", 1, NULL);
len = contents.mu_dsize;
if (contents.mu_dptr[len - 1] == 0)
len--;
mu_stream_write (pd->stream, contents.mu_dptr, len, NULL);
mu_stream_write (pd->stream, "\n", 1, NULL);
mu_dbm_datum_free (&contents);
return 0;
}
static void
iterate_database (mu_dbm_file_t db,
int (*matcher) (const char *, void *), void *matcher_data,
int (*action) (struct mu_dbm_datum const *, void *),
void *action_data)
{
int rc;
struct mu_dbm_datum key;
char *buf = NULL;
size_t bufsize = 0;
memset (&key, 0, sizeof key);
for (rc = mu_dbm_firstkey (db, &key); rc == 0;
rc = mu_dbm_nextkey (db, &key))
{
if (include_zero == -1)
include_zero = key.mu_dptr[key.mu_dsize-1] == 0;
if (matcher)
{
if (key.mu_dsize + 1 > bufsize)
{
bufsize = key.mu_dsize + 1;
buf = xrealloc (buf, bufsize);
}
memcpy (buf, key.mu_dptr, key.mu_dsize);
buf[key.mu_dsize] = 0;
if (!matcher (buf, matcher_data))
continue;
}
if (action (&key, action_data))
break;
}
free (buf);
}
static int
match_literal (const char *str, void *data)
{
char **argv = data;
for (; *argv; argv++)
{
if ((case_sensitive ? strcmp : strcasecmp) (str, *argv) == 0)
return 1;
}
return 0;
}
#ifndef FNM_CASEFOLD
# define FNM_CASEFOLD 0
#endif
static int
match_glob (const char *str, void *data)
{
char **argv = data;
for (; *argv; argv++)
{
if (fnmatch (*argv, str, case_sensitive ? FNM_CASEFOLD : 0) == 0)
return 1;
}
return 0;
}
struct regmatch
{
int regc;
regex_t *regs;
};
static int
match_regex (const char *str, void *data)
{
struct regmatch *match = data;
int i;
for (i = 0; i < match->regc; i++)
{
if (regexec (&match->regs[i], str, 0, NULL, 0) == 0)
return 1;
}
return 0;
}
void
compile_regexes (int argc, char **argv, struct regmatch *match)
{
regex_t *regs = xcalloc (argc, sizeof (regs[0]));
int i;
int cflags = (case_sensitive ? 0: REG_ICASE) | REG_EXTENDED | REG_NOSUB;
int errors = 0;
for (i = 0; i < argc; i++)
{
int rc = regcomp (&regs[i], argv[i], cflags);
if (rc)
{
char errbuf[512];
regerror (rc, &regs[i], errbuf, sizeof (errbuf));
mu_error (_("error compiling `%s': %s"), argv[i], errbuf);
errors++;
}
}
if (errors)
exit (EX_USAGE);
match->regc = argc;
match->regs = regs;
}
static void
free_regexes (struct regmatch *match)
{
int i;
for (i = 0; i < match->regc; i++)
regfree (&match->regs[i]);
free (match->regs);
}
static void
list_database (int argc, char **argv)
{
mu_dbm_file_t db = open_db_file (MU_STREAM_READ);
struct print_data pdata;
pdata.db = db;
pdata.stream = mu_strout;
if (argc == 0)
iterate_database (db, NULL, NULL, print_action, &pdata);
else
{
switch (key_type)
{
case key_literal:
iterate_database (db, match_literal, argv, print_action, &pdata);
break;
case key_glob:
iterate_database (db, match_glob, argv, print_action, &pdata);
break;
case key_regex:
{
struct regmatch m;
compile_regexes (argc, argv, &m);
iterate_database (db, match_regex, &m, print_action, &pdata);
free_regexes (&m);
}
}
}
mu_dbm_destroy (&db);
}
void
add_records (int mode, int replace)
{
mu_dbm_file_t db;
mu_stream_t input, flt;
const char *flt_argv[] = { "inline-comment", "#", "-S", "-i", "#", NULL };
char *buf = NULL;
size_t size = 0;
size_t len;
unsigned long line;
int rc;
if (input_file)
{
rc = mu_file_stream_create (&input, input_file, MU_STREAM_READ);
if (rc)
{
mu_error (_("cannot open input file %s: %s"), input_file,
mu_strerror (rc));
exit (EX_UNAVAILABLE);
}
}
else
input = mu_strin;
rc = mu_filter_create_args (&flt, input, "inline-comment",
MU_ARRAY_SIZE (flt_argv) - 1, flt_argv,
MU_FILTER_DECODE, MU_STREAM_READ);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_filter_create_args", input_file, rc);
exit (EX_UNAVAILABLE);
}
mu_stream_unref (input);
input = flt;
db = open_db_file (mode);
line = 1;
if (!input_file)
input_file = "<stdin>";
while ((rc = mu_stream_getline (input, &buf, &size, &len)) == 0
&& len > 0)
{
struct mu_dbm_datum key, contents;
char *kstr, *val;
mu_rtrim_class (buf, MU_CTYPE_ENDLN);
if (buf[0] == '#')
{
line = strtoul (buf + 1, NULL, 10);
continue;
}
kstr = mu_str_stripws (buf);
val = mu_str_skip_class_comp (kstr, MU_CTYPE_SPACE);
*val++ = 0;
val = mu_str_skip_class (val, MU_CTYPE_SPACE);
if (*val == 0)
{
mu_error (_("%s:%lu: malformed line"), input_file, line);
line++;
continue;
}
init_datum (&key, kstr);
init_datum (&contents, val);
rc = mu_dbm_store (db, &key, &contents, replace);
if (rc)
mu_error (_("%s:%lu: cannot store datum: %s"),
input_file, line,
rc == MU_ERR_FAILURE ?
mu_dbm_strerror (db) : mu_strerror (rc));
line++;
}
mu_dbm_destroy (&db);
mu_stream_unref (input);
}
static void
create_database ()
{
if (copy_permissions)
{
struct stat st;
if (!input_file)
{
mu_error (_("--copy-permissions used without --file"));
exit (EX_USAGE);
}
if (stat (input_file, &st))
{
mu_diag_funcall (MU_DIAG_ERROR, "stat", input_file, errno);
exit (EX_UNAVAILABLE);
}
owner_uid = st.st_uid;
owner_gid = st.st_gid;
permissions = st.st_mode & 0777;
}
else if (auth)
{
if (owner_uid == -1)
owner_uid = auth->uid;
if (owner_gid == -1)
owner_gid = auth->gid;
}
add_records (MU_STREAM_CREAT, 0);
}
static int
store_to_list (struct mu_dbm_datum const *key, void *data)
{
int rc;
mu_list_t list = data;
char *p = xmalloc (key->mu_dsize + 1);
memcpy (p, key->mu_dptr, key->mu_dsize);
p[key->mu_dsize] = 0;
rc = mu_list_append (list, p);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_list_append", p, rc);
exit (EX_SOFTWARE);
}
return 0;
}
static int
do_delete (void *item, void *data)
{
char *str = item;
mu_dbm_file_t db = data;
struct mu_dbm_datum key;
int rc;
init_datum (&key, str);
rc = mu_dbm_delete (db, &key);
if (rc == MU_ERR_NOENT)
{
mu_error (_("cannot remove record for %s: %s"),
str, mu_strerror (rc));
}
else if (rc)
{
mu_error (_("cannot remove record for %s: %s"),
str, mu_dbm_strerror (db));
if (rc != MU_ERR_NOENT)
exit (EX_UNAVAILABLE);
}
return 0;
}
static void
delete_database (int argc, char **argv)
{
mu_dbm_file_t db = open_db_file (MU_STREAM_RDWR);
mu_list_t templist = NULL;
int rc, i;
if (argc == 0)
{
mu_error (_("not enough arguments for delete"));
exit (EX_USAGE);
}
/* Collect matching keys */
rc = mu_list_create (&templist);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_list_create", NULL, rc);
exit (EX_SOFTWARE);
}
mu_list_set_destroy_item (templist, mu_list_free_item);
switch (key_type)
{
case key_literal:
for (i = 0; i < argc; i++)
{
char *p = xstrdup (argv[i]);
rc = mu_list_append (templist, p);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_list_append", p, rc);
exit (EX_SOFTWARE);
}
}
break;
case key_glob:
iterate_database (db, match_glob, argv,
store_to_list, templist);
break;
case key_regex:
{
struct regmatch m;
compile_regexes (argc, argv, &m);
iterate_database (db, match_regex, &m, store_to_list, templist);
free_regexes (&m);
}
}
mu_list_do (templist, do_delete, db);
mu_list_destroy (&templist);
mu_dbm_destroy (&db);
}
/*
mu dbm --create a.db < input
mu dbm --list a.db
mu dbm --delete a.db key [key...]
mu dbm --add a.db < input
mu dbm --replace a.db < input
*/
static struct argp_option dbm_options[] = {
{ NULL, 0, NULL, 0, N_("Operation mode"), 0},
{ "create", 'c', NULL, 0, N_("create the database") },
{ "list", 'l', NULL, 0, N_("list contents of the database") },
{ "delete", 'd', NULL, 0, N_("delete specified keys from the database") },
{ "add", 'a', NULL, 0, N_("add records to the database") },
{ "replace",'r', NULL, 0, N_("add records replacing ones with matching keys") },
{ NULL, 0, NULL, 0, N_("Create modifiers"), 0},
{ "file", 'f', N_("FILE"), 0,
N_("read input from FILE (with --create, --delete, --add and --replace)") },
{ "permissions", 'p', N_("NUM"), 0,
N_("set permissions on the created database") },
{ "user", 'u', N_("USER"), 0,
N_("set database owner name") },
{ "group", 'g', N_("GROUP"), 0,
N_("set database owner group") },
{ "copy-permissions", 'P', NULL, 0,
N_("copy database permissions and ownership from the input file") },
{ NULL, 0, NULL, 0, N_("List and Delete modifiers"), 0},
{ "glob", 'G', NULL, 0,
N_("treat keys as globbing patterns") },
{ "regex", 'R', NULL, 0,
N_("treat keys as regular expressions") },
{ "ignore-case", 'i', NULL, 0,
N_("case-insensitive matches") },
{ NULL, 0, NULL, 0, N_("Data length modifiers"), 0 },
{ "count-null", 'N', NULL, 0,
N_("data length accounts for terminating zero") },
{ "no-count-null", 'n', NULL, 0,
N_("data length does not account for terminating zero") },
{ NULL }
};
static error_t
dbm_parse_opt (int key, char *arg, struct argp_state *state)
{
switch (key)
{
case 'c':
mode = mode_create;
break;
case 'l':
mode = mode_list;
break;
case 'd':
mode = mode_delete;
break;
case 'a':
mode = mode_add;
break;
case 'r':
mode = mode_replace;
break;
case 'f':
input_file = arg;
break;
case 'p':
{
char *p;
unsigned long d = strtoul (arg, &p, 8);
if (*p || (d & ~0777))
argp_error (state, _("invalid file mode: %s"), arg);
permissions = d;
}
break;
case 'P':
copy_permissions = 1;
break;
case 'u':
auth = mu_get_auth_by_name (arg);
if (!auth)
{
char *p;
unsigned long n = strtoul (arg, &p, 0);
if (*p == 0)
owner_uid = n;
else
argp_error (state, _("no such user: %s"), arg);
}
break;
case 'g':
{
struct group *gr = getgrnam (arg);
if (!gr)
{
char *p;
unsigned long n = strtoul (arg, &p, 0);
if (*p == 0)
owner_gid = n;
else
argp_error (state, _("no such group: %s"), arg);
}
else
owner_gid = gr->gr_gid;
}
break;
case 'G':
key_type = key_glob;
break;
case 'R':
key_type = key_regex;
break;
case 'i':
case_sensitive = 0;
break;
case 'N':
include_zero = 1;
break;
case 'n':
include_zero = 0;
break;
default:
return ARGP_ERR_UNKNOWN;
}
return 0;
}
static struct argp dbm_argp = {
dbm_options,
dbm_parse_opt,
dbm_args_doc,
dbm_doc,
NULL,
NULL,
NULL
};
int
mutool_dbm (int argc, char **argv)
{
int index;
if (argp_parse (&dbm_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
return 1;
argc -= index;
argv += index;
if (argc == 0)
{
mu_error (_("database name not given"));
exit (EX_USAGE);
}
db_name = *argv++;
--argc;
switch (mode)
{
case mode_list:
list_database (argc, argv);
break;
case mode_create:
if (argc)
{
mu_error (_("too many arguments for create"));
exit (EX_USAGE);
}
create_database ();
break;
case mode_delete:
delete_database (argc, argv);
break;
case mode_add:
if (argc)
{
mu_error (_("too many arguments for add"));
exit (EX_USAGE);
}
add_records (MU_STREAM_RDWR, 0);
break;
case mode_replace:
if (argc)
{
mu_error (_("too many arguments for replace"));
exit (EX_USAGE);
}
add_records (MU_STREAM_RDWR, 1);
break;
}
return 0;
}
/*
MU Setup: dbm
mu-handler: mutool_dbm
mu-docstring: dbm_docstring
End MU Setup:
*/
......@@ -38,36 +38,52 @@ static struct argp ldflags_argp = {
#ifdef WITH_TLS
# define NEEDAUTH 1
# define NEEDAUTH "-lmu_auth " AUTHLIBS
#else
# define NEEDAUTH 0
# define NEEDAUTH NULL
#endif
#define NOTALL 2
#define NOTALL 1
struct lib_descr {
char *name;
char *libname;
int weight;
int flags;
} lib_descr[] = {
{ "mbox", "mu_mbox", 0 },
{ "mbox", "-lmu_mbox", 0 },
#ifdef ENABLE_MH
{ "mh", "mu_mh", 0 },
{ "mh", "-lmu_mh", 0 },
#endif
#ifdef ENABLE_MAILDIR
{ "maildir","mu_maildir", 0 },
{ "maildir", "-lmu_maildir", 0 },
#endif
#ifdef ENABLE_IMAP
{ "imap", "mu_imap", NEEDAUTH },
{ "imap", "-lmu_imap", 0 },
{ "imap", NEEDAUTH, 2 },
#endif
#ifdef ENABLE_POP
{ "pop", "mu_pop", NEEDAUTH },
{ "pop", "-lmu_pop", 0 },
{ "pop", NEEDAUTH, 2 },
#endif
#ifdef ENABLE_NNTP
{ "nntp", "mu_nntp", 0 },
{ "nntp", "-lmu_nntp", 0 },
#endif
{ "mailer", "mu_mailer", 0 },
{ "sieve", "mu_sieve", NOTALL },
{ "compat", "mu_compat" },
#ifdef ENABLE_DBM
{ "dbm", "-lmu_dbm", 0 },
{ "dbm", DBMLIBS, 2 },
#endif
{ "mailer", "-lmu_mailer", 0 },
{ "sieve", "-lmu_sieve", 0, NOTALL },
{ "compat", "-lmu_compat", 0 },
{ "auth", "-lmu_auth " AUTHLIBS, 2 },
#ifdef WITH_GUILE
{ "guile", "-lmu_scm " GUILE_LIBS, -1, NOTALL },
#endif
#ifdef WITH_PYTHON
{ "python", "-lmu_py " PYTHON_LIBS, -1, NOTALL },
#endif
{ "cfg", "-lmu_cfg", -1, NOTALL },
{ "argp", "-lmu_argp", -2, NOTALL },
{ NULL }
};
......@@ -82,6 +98,9 @@ void
add_entry (int level, char *ptr)
{
int i;
if (!ptr || !*ptr)
return;
if (nentry >= sizeof(lib_entry)/sizeof(lib_entry[0]))
{
mu_error (_("too many arguments"));
......@@ -122,7 +141,6 @@ int
mutool_ldflags (int argc, char **argv)
{
int i, j;
char *ptr;
if (argp_parse (&ldflags_argp, argc, argv, ARGP_IN_ORDER, &i, NULL))
return 1;
......@@ -140,21 +158,7 @@ mutool_ldflags (int argc, char **argv)
for ( ; argc > 0; argc--, argv++)
{
if (strcmp (argv[0], "auth") == 0)
add_entry (2, "-lmu_auth " AUTHLIBS);
#ifdef WITH_GUILE
else if (strcmp (argv[0], "guile") == 0)
add_entry (-1, "-lmu_scm " GUILE_LIBS);
#endif
#ifdef WITH_PYTHON
else if (strcmp (argv[0], "python") == 0)
add_entry (-1, "-lmu_py " PYTHON_LIBS);
#endif
else if (strcmp (argv[0], "cfg") == 0)
add_entry (-1, "-lmu_cfg");
else if (strcmp (argv[0], "argp") == 0)
add_entry (-2, "-lmu_argp");
else if (strcmp (argv[0], "all") == 0)
if (strcmp (argv[0], "all") == 0)
{
struct lib_descr *p;
......@@ -162,28 +166,24 @@ mutool_ldflags (int argc, char **argv)
{
if (p->flags & NOTALL)
continue;
mu_asprintf (&ptr, "-l%s", p->libname);
add_entry (0, ptr);
if (p->flags & NEEDAUTH)
add_entry (2, "-lmu_auth " AUTHLIBS);
add_entry (p->weight, p->libname);
}
}
else
{
struct lib_descr *p;
int found = 0;
for (p = lib_descr; p->name; p++)
{
if (mu_c_strcasecmp (p->name, argv[0]) == 0)
break;
if (p->name)
{
mu_asprintf (&ptr, "-l%s", p->libname);
add_entry (0, ptr);
if (p->flags & NEEDAUTH)
add_entry (2, "-lmu_auth " AUTHLIBS);
add_entry (p->weight, p->libname);
found = 1;
}
else
}
if (!found)
{
mu_error (_("unknown keyword: %s"), argv[0]);
return 1;
......
......@@ -46,6 +46,10 @@ pop3d_SOURCES =\
uidl.c\
user.c
if MU_COND_DBM
LIBMU_DBM=../libmu_dbm/libmu_dbm.la
endif
pop3d_LDADD = \
${MU_APP_LIBRARIES}\
${MU_LIB_MBOX}\
......@@ -54,15 +58,25 @@ pop3d_LDADD = \
${MU_LIB_AUTH}\
@MU_AUTHLIBS@ \
${MU_LIB_MAILUTILS}\
@MU_COMMON_LIBRARIES@ @TCPWRAP_LIBRARIES@
@MU_COMMON_LIBRARIES@\
${LIBMU_DBM}\
@DBMLIBS@\
@TCPWRAP_LIBRARIES@
popauth_SOURCES = popauth.c
popauth_LDADD = ${MU_APP_LIBRARIES} ${MU_LIB_MAILUTILS} @MU_COMMON_LIBRARIES@
popauth_LDADD = \
${MU_APP_LIBRARIES}\
${MU_LIB_MAILUTILS}\
@MU_COMMON_LIBRARIES@\
${LIBMU_DBM}\
@DBMLIBS@
pop3d_DEPENDENCIES = \
@MU_AUTHLIBS_DEPENDENCY@ \
../lib/libmuaux.a \
${MU_LIB_MBOX}\
${MU_LIB_MH}\
${MU_LIB_MAILDIR}\
${MU_LIB_MAILUTILS}
${MU_LIB_MAILUTILS}\
${LIBMU_DBM}
......
......@@ -43,59 +43,85 @@ pop3d_apopuser (const char *user)
{
char *password = NULL;
#ifdef USE_DBM
#ifdef ENABLE_DBM
{
size_t len;
DBM_FILE db;
DBM_DATUM key, data;
mu_dbm_file_t db;
struct mu_dbm_datum key, data;
int rc;
int rc = mu_dbm_open (APOP_PASSFILE, &db, MU_STREAM_READ, 0600);
rc = mu_dbm_create (APOP_PASSFILE, &db);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR, _("unable to create APOP db"));
return NULL;
}
rc = mu_dbm_safety_check (db);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR,
_("APOP file %s fails safety check: %s"),
APOP_PASSFILE, mu_strerror (rc));
mu_dbm_destroy (&db);
return NULL;
}
rc = mu_dbm_open (db, MU_STREAM_READ, 0600);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR, _("unable to open APOP db: %s"),
mu_strerror (errno));
mu_strerror (rc));
return NULL;
}
memset (&key, 0, sizeof key);
memset (&data, 0, sizeof data);
MU_DATUM_PTR (key) = (void*) user;
MU_DATUM_SIZE (key) = strlen (user);
key.mu_dptr = (void *)user;
key.mu_dsize = strlen (user);
rc = mu_dbm_fetch (db, key, &data);
mu_dbm_close (db);
if (rc)
rc = mu_dbm_fetch (db, &key, &data);
if (rc == MU_ERR_NOENT)
{
mu_dbm_destroy (&db);
return NULL;
}
else if (rc)
{
mu_diag_output (MU_DIAG_ERROR,
_("cannot fetch APOP data: %s"), mu_strerror (errno));
_("cannot fetch APOP data: %s"),
mu_dbm_strerror (db));
mu_dbm_destroy (&db);
return NULL;
}
len = MU_DATUM_SIZE (data);
mu_dbm_destroy (&db);
len = data.mu_dsize;
password = malloc (len + 1);
if (password == NULL)
{
mu_dbm_datum_free (&data);
return NULL;
}
memcpy (password, MU_DATUM_PTR (data), len);
memcpy (password, data.mu_dptr, len);
password[len] = 0;
mu_dbm_datum_free (&data);
return password;
}
#else /* !USE_DBM */
#else /* !ENABLE_DBM */
{
char *buf = NULL;
size_t size = 0;
size_t ulen;
FILE *apop_file;
if (mu_check_perm (APOP_PASSFILE, 0600))
{
mu_diag_output (MU_DIAG_INFO,
_("bad permissions on APOP password file"));
return NULL;
}
/* FIXME */
/* if (mu_check_perm (APOP_PASSFILE, 0600)) */
/* { */
/* mu_diag_output (MU_DIAG_INFO, */
/* _("bad permissions on APOP password file")); */
/* return NULL; */
/* } */
apop_file = fopen (APOP_PASSFILE, "r");
if (apop_file == NULL)
......
......@@ -113,12 +113,12 @@ write_popbull_file (size_t num)
return rc;
}
#ifdef USE_DBM
#ifdef ENABLE_DBM
int
read_bulletin_db (size_t *pnum)
{
DBM_FILE db;
DBM_DATUM key, data;
mu_dbm_file_t db;
struct mu_dbm_datum key, data;
int rc;
char sbuf[128];
char *bufptr;
......@@ -126,45 +126,59 @@ read_bulletin_db (size_t *pnum)
size_t s;
char *p;
rc = mu_dbm_open (bulletin_db_name, &db, MU_STREAM_READ, 0660);
rc = mu_dbm_create (bulletin_db_name, &db);
if (rc)
{
if (errno == ENOENT)
mu_diag_output (MU_DIAG_ERROR, _("unable to create bulletin db"));
return rc;
}
rc = mu_dbm_safety_check (db);
if (rc)
{
if (rc == ENOENT)
{
*pnum = 0;
return 0;
}
else
mu_diag_output (MU_DIAG_ERROR,
_("bulletin db %s fails safety check: %s"),
bulletin_db_name, mu_strerror (rc));
mu_dbm_destroy (&db);
return 1;
}
rc = mu_dbm_open (db, MU_STREAM_READ, 0660);
if (rc)
{
mu_error (_("unable to open bulletin db for reading: %s"),
mu_strerror (errno));
mu_strerror (rc));
return rc;
}
}
memset (&key, 0, sizeof key);
memset (&data, 0, sizeof data);
MU_DATUM_PTR(key) = username;
MU_DATUM_SIZE(key) = strlen (username);
key.mu_dptr = username;
key.mu_dsize = strlen (username);
rc = mu_dbm_fetch (db, key, &data);
rc = mu_dbm_fetch (db, &key, &data);
if (rc)
{
int ec = errno;
if (ec == ENOENT)
if (rc == MU_ERR_NOENT)
{
*pnum = 0;
return 0;
}
else if (rc)
{
mu_error (_("cannot fetch bulletin db data: %s"),
mu_strerror (ec));
mu_dbm_close (db);
mu_dbm_strerror (db));
mu_dbm_destroy (&db);
return 1;
}
mu_dbm_destroy (&db);
s = MU_DATUM_SIZE (data);
s = data.mu_dsize;
if (s < sizeof sbuf)
bufptr = sbuf;
else
......@@ -172,16 +186,15 @@ read_bulletin_db (size_t *pnum)
buf = malloc (s + 1);
if (!buf)
{
mu_error("%s", mu_strerror (errno));
mu_error ("%s", mu_strerror (errno));
return 1;
}
bufptr = buf;
}
memcpy (bufptr, MU_DATUM_PTR (data), s);
memcpy (bufptr, data.mu_dptr, s);
bufptr[s] = 0;
mu_dbm_datum_free(&data);
mu_dbm_close (db);
mu_dbm_datum_free (&data);
rc = 1;
*pnum = strtoul (bufptr, &p, 0);
......@@ -189,27 +202,9 @@ read_bulletin_db (size_t *pnum)
rc = 0;
else
{
#ifdef QPOPPER_COMPAT
if (s == sizeof long)
{
long n;
n = *(long*)MU_DATUM_PTR (data);
if (n >= 0)
{
mu_diag_output (MU_DIAG_INFO,
_("assuming bulletin database is in qpopper format"));
*pnum = n;
rc = 0;
}
}
else
#endif /* QPOPPER_COMPAT */
{
mu_error (_("wrong bulletin database format for `%s'"),
username);
}
}
free (buf);
return rc;
......@@ -218,41 +213,60 @@ read_bulletin_db (size_t *pnum)
int
write_bulletin_db (size_t num)
{
DBM_FILE db;
DBM_DATUM key, data;
mu_dbm_file_t db;
struct mu_dbm_datum key, data;
int rc;
const char *p;
rc = mu_dbm_open (bulletin_db_name, &db, MU_STREAM_RDWR, 0660);
rc = mu_dbm_create (bulletin_db_name, &db);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR, _("unable to create bulletin db"));
return rc;
}
rc = mu_dbm_safety_check (db);
if (rc && rc != ENOENT)
{
mu_diag_output (MU_DIAG_ERROR,
_("bulletin db %s fails safety check: %s"),
bulletin_db_name, mu_strerror (rc));
mu_dbm_destroy (&db);
return rc;
}
rc = mu_dbm_open (db, MU_STREAM_RDWR, 0660);
if (rc)
{
mu_error (_("unable to open bulletin db for writing: %s"),
mu_strerror (errno));
mu_strerror (rc));
mu_dbm_destroy (&db);
return rc;
}
memset (&key, 0, sizeof key);
memset (&data, 0, sizeof data);
MU_DATUM_PTR (key) = username;
MU_DATUM_SIZE (key) = strlen (username);
key.mu_dptr = username;
key.mu_dsize = strlen (username);
p = mu_umaxtostr (0, num);
MU_DATUM_PTR (data) = (char *) p;
MU_DATUM_SIZE (data) = strlen (p);
data.mu_dptr = (char *) p;
data.mu_dsize = strlen (p);
rc = mu_dbm_insert (db, key, data, 1);
rc = mu_dbm_store (db, &key, &data, 1);
if (rc)
mu_error (_("cannot store datum in bulletin db"));
mu_error (_("cannot store datum in bulletin db: %s"),
mu_dbm_strerror (db));
mu_dbm_close (db);
mu_dbm_destroy (&db);
return rc;
}
#endif /* USE_DBM */
#endif /* ENABLE_DBM */
int
get_last_delivered_num (size_t *pret)
{
#ifdef USE_DBM
#ifdef ENABLE_DBM
if (bulletin_db_name && read_bulletin_db (pret) == 0)
return 0;
#endif
......@@ -262,7 +276,7 @@ get_last_delivered_num (size_t *pret)
void
store_last_delivered_num (size_t num)
{
#ifdef USE_DBM
#ifdef ENABLE_DBM
if (bulletin_db_name && write_bulletin_db (num) == 0)
return;
#endif
......
......@@ -19,27 +19,45 @@
#ifdef ENABLE_LOGIN_DELAY
static int
open_stat_db (DBM_FILE *db, int mode)
static mu_dbm_file_t
open_stat_db (int mode)
{
int rc = mu_dbm_open (login_stat_file, db, mode, 0660);
mu_dbm_file_t db;
int rc;
rc = mu_dbm_create (login_stat_file, &db);
if (rc)
{
if (rc == -1)
mu_diag_output (MU_DIAG_INFO, _("bad permissions on statistics db"));
else
mu_diag_output (MU_DIAG_ERROR, _("unable to open statistics db: %s"),
mu_diag_output (MU_DIAG_ERROR, _("unable to create statistics db"));
return NULL;
}
rc = mu_dbm_safety_check (db);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR,
_("statistics db fails safety check: %s"),
mu_strerror (rc));
mu_dbm_destroy (&db);
return NULL;
}
return rc;
rc = mu_dbm_open (db, mode, 0660);
if (rc)
{
mu_diag_output (MU_DIAG_ERROR, _("unable to open statistics db: %s"),
mu_dbm_strerror (db));
mu_dbm_destroy (&db);
}
return db;
}
int
check_login_delay (char *username)
{
time_t now, prev_time;
DBM_FILE db;
DBM_DATUM key, data;
mu_dbm_file_t db;
struct mu_dbm_datum key, data;
char text[64], *p;
int rc;
......@@ -47,35 +65,38 @@ check_login_delay (char *username)
return 0;
time (&now);
if (open_stat_db (&db, MU_STREAM_RDWR))
db = open_stat_db (MU_STREAM_READ);
if (!db)
return 0;
memset (&key, 0, sizeof key);
MU_DATUM_PTR(key) = username;
MU_DATUM_SIZE(key) = strlen (username);
key.mu_dptr = username;
key.mu_dsize = strlen (username);
memset (&data, 0, sizeof data);
rc = mu_dbm_fetch (db, key, &data);
rc = mu_dbm_fetch (db, &key, &data);
if (rc)
{
if (rc != MU_ERR_NOENT)
mu_diag_output (MU_DIAG_ERROR, _("cannot fetch login delay data: %s"),
mu_strerror (rc));
mu_dbm_close (db);
mu_dbm_strerror (db));
mu_dbm_destroy (&db);
return 0;
}
if (MU_DATUM_SIZE(data) > sizeof (text) - 1)
if (data.mu_dsize > sizeof (text) - 1)
{
mu_diag_output (MU_DIAG_ERROR,
_("invalid entry for '%s': wrong timestamp size"),
username);
mu_dbm_close (db);
mu_dbm_destroy (&db);
return 0;
}
mu_dbm_destroy (&db);
memcpy (text, MU_DATUM_PTR(data), MU_DATUM_SIZE(data));
text[MU_DATUM_SIZE(data)] = 0;
mu_dbm_close (db);
memcpy (text, data.mu_dptr, data.mu_dsize);
text[data.mu_dsize] = 0;
mu_dbm_datum_free (&data);
prev_time = strtoul (text, &p, 0);
if (*p)
......@@ -93,40 +114,42 @@ void
update_login_delay (char *username)
{
time_t now;
DBM_FILE db;
DBM_DATUM key, data;
mu_dbm_file_t db;
struct mu_dbm_datum key, data;
char text[64];
if (login_delay == 0 || username == NULL)
return;
time (&now);
if (open_stat_db (&db, MU_STREAM_RDWR))
db = open_stat_db (MU_STREAM_RDWR);
if (!db)
return;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
MU_DATUM_PTR(key) = username;
MU_DATUM_SIZE(key) = strlen (username);
key.mu_dptr = username;
key.mu_dsize = strlen (username);
snprintf (text, sizeof text, "%lu", (unsigned long) now);
MU_DATUM_PTR(data) = text;
MU_DATUM_SIZE(data) = strlen (text);
if (mu_dbm_insert (db, key, data, 1))
mu_error (_("%s: cannot store datum %s/%s"),
login_stat_file, username, text);
mu_dbm_close (db);
data.mu_dptr = text;
data.mu_dsize = strlen (text);
if (mu_dbm_store (db, &key, &data, 1))
mu_error (_("%s: cannot store datum %s/%s: %s"),
login_stat_file, username, text,
mu_dbm_strerror (db));
mu_dbm_destroy (&db);
}
void
login_delay_capa ()
{
DBM_FILE db;
mu_dbm_file_t db;
if (login_delay && open_stat_db (&db, MU_STREAM_RDWR) == 0)
if (login_delay && (db = open_stat_db (MU_STREAM_RDWR)) != NULL)
{
pop3d_outf ("LOGIN-DELAY %s\n", mu_umaxtostr (0, login_delay));
mu_dbm_close (db);
mu_dbm_destroy (&db);
}
}
#endif
......
......@@ -77,7 +77,7 @@ cb_bulletin_source (void *data, mu_config_value_t *val)
return 0;
}
#ifdef USE_DBM
#ifdef ENABLE_DBM
static int
cb_bulletin_db (void *data, mu_config_value_t *val)
{
......@@ -111,7 +111,7 @@ static struct mu_cfg_param pop3d_cfg_param[] = {
{ "bulletin-source", mu_cfg_callback, NULL, 0, cb_bulletin_source,
N_("Get bulletins from the specified mailbox."),
N_("url") },
#ifdef USE_DBM
#ifdef ENABLE_DBM
{ "bulletin-db", mu_cfg_callback, NULL, 0, cb_bulletin_db,
N_("Set the bulletin database file name."),
N_("file") },
......
......@@ -24,7 +24,7 @@
#include <mailutils/types.h>
#include <mailutils/stream.h>
#include <mailutils/io.h>
#include <mu_dbm.h>
#include <mailutils/dbm.h>
#include <mu_umaxtostr.h>
#include <muaux.h>
......@@ -35,7 +35,7 @@
type automatically */
#define APOP_PASSFILE_NAME "apop"
#ifdef USE_DBM
#ifdef ENABLE_DBM
# define APOP_PASSFILE SYSCONFDIR "/" APOP_PASSFILE_NAME
# define ENABLE_LOGIN_DELAY
#else
......
......@@ -73,7 +73,7 @@ static struct argp_option options[] =
{ NULL, 0, NULL, 0,
N_("Default action is:\n"
" For the file owner: --list\n"
" For root: --list\n"
" For a user: --modify --user <username>\n"), 2 },
{ NULL, 0, NULL, 0, N_("Options are:"), 3 },
......@@ -197,7 +197,7 @@ popauth_parse_opt (int key, char *arg, struct argp_state *astate)
}
int
main(int argc, char **argv)
main (int argc, char **argv)
{
struct action_data adata;
......@@ -223,40 +223,120 @@ check_action (int action)
}
}
int
check_user_perm (int action, struct action_data *ap)
mu_dbm_file_t
open_db_file (int action, struct action_data *ap, int *my_file)
{
struct stat sb;
mu_dbm_file_t db;
struct passwd *pw;
uid_t uid;
int rc;
int flags = 0;
char *db_name = NULL;
int fd;
struct stat sb;
int safety_flags = MU_FILE_SAFETY_ALL & ~MU_FILE_SAFETY_OWNER_MISMATCH;
switch (action)
{
case ACT_CREATE:
flags = MU_STREAM_CREAT;
safety_flags = MU_FILE_SAFETY_NONE;
db_name = ap->output_name;
break;
case ACT_ADD:
case ACT_DELETE:
if (!ap->input_name)
ap->input_name = APOP_PASSFILE;
flags = MU_STREAM_RDWR;
db_name = ap->input_name;
break;
case ACT_LIST:
if (!ap->input_name)
ap->input_name = APOP_PASSFILE;
flags = MU_STREAM_READ;
safety_flags = MU_FILE_SAFETY_NONE;
db_name = ap->input_name;
break;
case ACT_CHPASS:
if (!ap->input_name)
ap->input_name = APOP_PASSFILE;
flags = MU_STREAM_RDWR;
db_name = ap->input_name;
break;
default:
abort ();
}
uid = getuid ();
if (mu_dbm_stat (ap->input_name, &sb))
rc = mu_dbm_create (db_name, &db);
if (rc)
{
if (ap->action == ACT_ADD)
mu_diag_output (MU_DIAG_ERROR, _("unable to create database %s: %s"),
db_name, mu_strerror (rc));
exit (EX_SOFTWARE);
}
// mu_dbm_safety_set_owner (db, uid);
/* Adjust safety flags */
if (permissions & 0002)
safety_flags &= ~MU_FILE_SAFETY_WORLD_WRITABLE;
if (permissions & 0004)
safety_flags &= ~MU_FILE_SAFETY_WORLD_READABLE;
if (permissions & 0020)
safety_flags &= ~MU_FILE_SAFETY_GROUP_WRITABLE;
if (permissions & 0040)
safety_flags &= ~MU_FILE_SAFETY_GROUP_READABLE;
mu_dbm_safety_set_flags (db, safety_flags);
rc = mu_dbm_safety_check (db);
if (rc && rc != ENOENT)
{
DBM_FILE db;
if (mu_dbm_open (ap->input_name, &db, MU_STREAM_CREAT, permissions))
mu_diag_output (MU_DIAG_ERROR,
_("%s fails safety check: %s"),
db_name, mu_strerror (rc));
mu_dbm_destroy (&db);
exit (EX_UNAVAILABLE);
}
rc = mu_dbm_open (db, flags, permissions);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "mu_dbm_open",
ap->input_name, errno);
db_name, rc);
exit (EX_SOFTWARE);
}
mu_dbm_close (db);
mu_dbm_stat (ap->input_name, &sb);
}
else
if (uid == 0)
return db;
rc = mu_dbm_get_fd (db, &fd, NULL);
if (rc)
{
mu_diag_funcall (MU_DIAG_ERROR, "stat", ap->input_name, errno);
exit (EX_OSERR);
mu_diag_funcall (MU_DIAG_ERROR, "mu_dbm_get_fd",
db_name, rc);
exit (EX_SOFTWARE);
}
if (fstat (fd, &sb))
{
mu_diag_funcall (MU_DIAG_ERROR, "fstat",
db_name, errno);
exit (EX_SOFTWARE);
}
uid = getuid ();
if (uid == 0 || sb.st_uid == uid)
return 0;
if (sb.st_uid == uid)
{
if (my_file)
*my_file = 1;
return db;
}
if (my_file)
*my_file = 0;
if (ap->username)
{
......@@ -273,41 +353,36 @@ check_user_perm (int action, struct action_data *ap)
if (!pw)
exit (EX_OSERR);
ap->username = pw->pw_name;
return 1;
return db;
}
static void
print_entry (mu_stream_t str, DBM_DATUM key, DBM_DATUM contents)
print_entry (mu_stream_t str, struct mu_dbm_datum const *key,
struct mu_dbm_datum const *contents)
{
if (compatibility_option)
mu_stream_printf (str, "%.*s: %.*s\n",
(int) MU_DATUM_SIZE (key),
(char*) MU_DATUM_PTR (key),
(int) MU_DATUM_SIZE (contents),
(char*) MU_DATUM_PTR (contents));
(int) key->mu_dsize,
(char*) key->mu_dptr,
(int) contents->mu_dsize,
(char*) contents->mu_dptr);
else
mu_stream_printf (str, "%.*s %.*s\n",
(int) MU_DATUM_SIZE (key),
(char*) MU_DATUM_PTR (key),
(int) MU_DATUM_SIZE (contents),
(char*) MU_DATUM_PTR (contents));
(int) key->mu_dsize,
(char*) key->mu_dptr,
(int) contents->mu_dsize,
(char*) contents->mu_dptr);
}
int
action_list (struct action_data *ap)
{
mu_stream_t str;
DBM_FILE db;
DBM_DATUM key;
DBM_DATUM contents;
mu_dbm_file_t db;
struct mu_dbm_datum key, contents;
int rc;
check_user_perm (ACT_LIST, ap);
if (mu_dbm_open (ap->input_name, &db, MU_STREAM_READ, 0))
{
mu_error (_("cannot open file %s: %s"),
ap->input_name, mu_strerror (errno));
return 1;
}
db = open_db_file (ACT_LIST, ap, NULL);
if (ap->output_name)
{
......@@ -331,32 +406,47 @@ action_list (struct action_data *ap)
{
memset (&key, 0, sizeof key);
memset (&contents, 0, sizeof contents);
MU_DATUM_PTR (key) = ap->username;
MU_DATUM_SIZE (key) = strlen (ap->username);
if (mu_dbm_fetch (db, key, &contents))
key.mu_dptr = ap->username;
key.mu_dsize = strlen (ap->username);
rc = mu_dbm_fetch (db, &key, &contents);
if (rc == MU_ERR_NOENT)
{
mu_error (_("no such user: %s"), ap->username);
}
else if (rc)
{
mu_error (_("database fetch error: %s"), mu_dbm_strerror (db));
exit (EX_UNAVAILABLE);
}
else
{
print_entry (str, key, contents);
print_entry (str, &key, &contents);
mu_dbm_datum_free (&contents);
}
}
else
{
for (key = mu_dbm_firstkey (db); MU_DATUM_PTR(key);
key = mu_dbm_nextkey (db, key))
memset (&key, 0, sizeof key);
for (rc = mu_dbm_firstkey (db, &key); rc == 0;
rc = mu_dbm_nextkey (db, &key))
{
memset (&contents, 0, sizeof contents);
mu_dbm_fetch (db, key, &contents);
print_entry (str, key, contents);
rc = mu_dbm_fetch (db, &key, &contents);
if (rc == 0)
{
print_entry (str, &key, &contents);
mu_dbm_datum_free (&contents);
}
else
{
mu_error (_("database fetch error: %s"), mu_dbm_strerror (db));
exit (EX_UNAVAILABLE);
}
mu_dbm_datum_free (&key);
}
}
mu_dbm_close (db);
mu_stream_destroy (&str);
mu_dbm_destroy (&db);
return 0;
}
......@@ -365,9 +455,8 @@ action_create (struct action_data *ap)
{
int rc;
mu_stream_t in;
DBM_FILE db;
DBM_DATUM key;
DBM_DATUM contents;
mu_dbm_file_t db;
struct mu_dbm_datum key, contents;
char *buf = NULL;
size_t size = 0, len;
int line = 0;
......@@ -399,12 +488,8 @@ action_create (struct action_data *ap)
if (!ap->output_name)
ap->output_name = APOP_PASSFILE;
if (mu_dbm_open (ap->output_name, &db, MU_STREAM_CREAT, permissions))
{
mu_error (_("cannot create database %s: %s"),
ap->output_name, mu_strerror (errno));
return 1;
}
db = open_db_file (ACT_CREATE, ap, NULL);
line = 0;
while ((rc = mu_stream_getline (in, &buf, &size, &len)) == 0
......@@ -435,20 +520,25 @@ action_create (struct action_data *ap)
memset (&key, 0, sizeof key);
memset (&contents, 0, sizeof contents);
MU_DATUM_PTR (key) = str;
MU_DATUM_SIZE (key) = strlen (str);
MU_DATUM_PTR (contents) = pass;
MU_DATUM_SIZE (contents) = strlen (pass);
key.mu_dptr = str;
key.mu_dsize = strlen (str);
contents.mu_dptr = pass;
contents.mu_dsize = strlen (pass);
if (mu_dbm_insert (db, key, contents, 1))
mu_error (_("%s:%d: cannot store datum"), ap->input_name, line);
rc = mu_dbm_store (db, &key, &contents, 1);
if (rc)
mu_error (_("%s:%d: cannot store datum: %s"),
ap->input_name, line,
rc == MU_ERR_FAILURE ?
mu_dbm_strerror (db) : mu_strerror (rc));
}
free (buf);
mu_dbm_close (db);
mu_dbm_destroy (&db);
mu_stream_destroy (&in);
return 0;
}
/*FIXME
int
open_io (int action, struct action_data *ap, DBM_FILE *db, int *not_owner)
{
......@@ -463,6 +553,7 @@ open_io (int action, struct action_data *ap, DBM_FILE *db, int *not_owner)
}
return 0;
}
*/
void
fill_pass (struct action_data *ap)
......@@ -527,9 +618,8 @@ fill_pass (struct action_data *ap)
int
action_add (struct action_data *ap)
{
DBM_FILE db;
DBM_DATUM key;
DBM_DATUM contents;
mu_dbm_file_t db;
struct mu_dbm_datum key, contents;
int rc;
if (!ap->username)
......@@ -538,31 +628,32 @@ action_add (struct action_data *ap)
return 1;
}
if (open_io (ACT_ADD, ap, &db, NULL))
return 1;
db = open_db_file (ACT_ADD, ap, NULL);
fill_pass (ap);
memset (&key, 0, sizeof key);
memset (&contents, 0, sizeof contents);
MU_DATUM_PTR (key) = ap->username;
MU_DATUM_SIZE (key) = strlen (ap->username);
MU_DATUM_PTR (contents) = ap->passwd;
MU_DATUM_SIZE (contents) = strlen (ap->passwd);
key.mu_dptr = ap->username;
key.mu_dsize = strlen (ap->username);
contents.mu_dptr = ap->passwd;
contents.mu_dsize = strlen (ap->passwd);
rc = mu_dbm_insert (db, key, contents, 1);
rc = mu_dbm_store (db, &key, &contents, 1);
if (rc)
mu_error (_("cannot store datum"));
mu_error (_("cannot store datum: %s"),
rc == MU_ERR_FAILURE ?
mu_dbm_strerror (db) : mu_strerror (rc));
mu_dbm_close (db);
mu_dbm_destroy (&db);
return rc;
}
int
action_delete (struct action_data *ap)
{
DBM_FILE db;
DBM_DATUM key;
mu_dbm_file_t db;
struct mu_dbm_datum key;
int rc;
if (!ap->username)
......@@ -571,56 +662,64 @@ action_delete (struct action_data *ap)
return 1;
}
if (open_io (ACT_DELETE, ap, &db, NULL))
return 1;
db = open_db_file (ACT_DELETE, ap, NULL);
MU_DATUM_PTR (key) = ap->username;
MU_DATUM_SIZE (key) = strlen (ap->username);
memset (&key, 0, sizeof key);
key.mu_dptr = ap->username;
key.mu_dsize = strlen (ap->username);
rc = mu_dbm_delete (db, key);
rc = mu_dbm_delete (db, &key);
if (rc)
mu_error (_("cannot remove record for %s"), ap->username);
mu_error (_("cannot remove record for %s: %s"),
ap->username,
rc == MU_ERR_FAILURE ?
mu_dbm_strerror (db) : mu_strerror (rc));
mu_dbm_close (db);
mu_dbm_destroy (&db);
return rc;
}
int
action_chpass (struct action_data *ap)
{
DBM_FILE db;
DBM_DATUM key;
DBM_DATUM contents;
mu_dbm_file_t db;
struct mu_dbm_datum key, contents;
int rc;
int not_owner;
int my_file;
if (open_io (ACT_CHPASS, ap, &db, &not_owner))
return 1;
db = open_db_file (ACT_CHPASS, ap, &my_file);
if (!ap->username)
{
mu_error (_("missing username"));
return 1;
struct passwd *pw = getpwuid (getuid ());
ap->username = pw->pw_name;
printf ("Changing password for %s\n", ap->username);
}
memset (&key, 0, sizeof key);
memset (&contents, 0, sizeof contents);
MU_DATUM_PTR (key) = ap->username;
MU_DATUM_SIZE (key) = strlen (ap->username);
if (mu_dbm_fetch (db, key, &contents))
key.mu_dptr = ap->username;
key.mu_dsize = strlen (ap->username);
rc = mu_dbm_fetch (db, &key, &contents);
if (rc == MU_ERR_NOENT)
{
mu_error (_("no such user: %s"), ap->username);
return 1;
}
else if (rc)
{
mu_error (_("database fetch error: %s"), mu_dbm_strerror (db));
exit (EX_UNAVAILABLE);
}
if (not_owner)
if (!my_file)
{
char *oldpass, *p;
oldpass = xmalloc (MU_DATUM_SIZE (contents) + 1);
memcpy (oldpass, MU_DATUM_PTR (contents), MU_DATUM_SIZE (contents));
oldpass[MU_DATUM_SIZE (contents)] = 0;
oldpass = xmalloc (contents.mu_dsize + 1);
memcpy (oldpass, contents.mu_dptr, contents.mu_dsize);
oldpass[contents.mu_dsize] = 0;
p = getpass (_("Old Password:"));
if (!p)
return 1;
......@@ -634,32 +733,49 @@ action_chpass (struct action_data *ap)
fill_pass (ap);
mu_dbm_datum_free (&contents);
MU_DATUM_PTR (contents) = ap->passwd;
MU_DATUM_SIZE (contents) = strlen (ap->passwd);
rc = mu_dbm_insert (db, key, contents, 1);
contents.mu_dptr = ap->passwd;
contents.mu_dsize = strlen (ap->passwd);
rc = mu_dbm_store (db, &key, &contents, 1);
if (rc)
mu_error (_("cannot replace datum"));
mu_error (_("cannot replace datum: %s"),
rc == MU_ERR_FAILURE ?
mu_dbm_strerror (db) : mu_strerror (rc));
mu_dbm_close (db);
mu_dbm_destroy (&db);
return rc;
}
void
popauth_version (FILE *stream, struct argp_state *state)
{
#if defined(WITH_GDBM)
# define FORMAT "GDBM"
#elif defined(WITH_BDB)
# define FORMAT "Berkeley DB"
#elif defined(WITH_NDBM)
# define FORMAT "NDBM"
#elif defined(WITH_OLD_DBM)
# define FORMAT "Old DBM"
#elif defined(WITH_TOKYOCABINET)
# define FORMAT "Tokyo Cabinet"
#endif
mu_iterator_t itr;
int rc;
mu_program_version_hook (stream, state);
fprintf (stream, _("Database format: %s\n"), FORMAT);
fprintf (stream, _("Database location: %s\n"), APOP_PASSFILE);
fprintf (stream, _("Database formats: "));
rc = mu_dbm_impl_iterator (&itr);
if (rc)
{
fprintf (stream, "%s\n", _("unknown"));
mu_error ("%s", mu_strerror (rc));
}
else
{
int i;
for (mu_iterator_first (itr), i = 0; !mu_iterator_is_done (itr);
mu_iterator_next (itr), i++)
{
struct mu_dbm_impl *impl;
mu_iterator_current (itr, (void**)&impl);
if (i)
fprintf (stream, ", ");
fprintf (stream, "%s", impl->_dbm_name);
}
fputc ('\n', stream);
mu_iterator_destroy (&itr);
}
fprintf (stream, _("Default database location: %s\n"), APOP_PASSFILE);
exit (EX_OK);
}
......