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 ...@@ -83,6 +83,10 @@ if MU_COND_SUPPORT_CXX
83 LIBMU_CPP_DIR = libmu_cpp 83 LIBMU_CPP_DIR = libmu_cpp
84 endif 84 endif
85 85
86 if MU_COND_DBM
87 LIBMU_DBM_DIR = libmu_dbm
88 endif
89
86 SUBDIRS = . \ 90 SUBDIRS = . \
87 mu-aux\ 91 mu-aux\
88 include\ 92 include\
...@@ -99,6 +103,7 @@ SUBDIRS = . \ ...@@ -99,6 +103,7 @@ SUBDIRS = . \
99 $(LIBMU_CPP_DIR)\ 103 $(LIBMU_CPP_DIR)\
100 $(GINT_DIR)\ 104 $(GINT_DIR)\
101 $(LIBMU_SCM_DIR)\ 105 $(LIBMU_SCM_DIR)\
106 $(LIBMU_DBM_DIR)\
102 libmu_sieve\ 107 libmu_sieve\
103 $(PYTHON_DIR)\ 108 $(PYTHON_DIR)\
104 doc\ 109 doc\
......
...@@ -88,7 +88,7 @@ AM_PROG_LIBTOOL ...@@ -88,7 +88,7 @@ AM_PROG_LIBTOOL
88 ## Predefine several variables used to display configuration status 88 ## Predefine several variables used to display configuration status
89 status_pam=no 89 status_pam=no
90 status_ltdl=no 90 status_ltdl=no
91 status_dbm=no 91 status_dbm=
92 status_gsasl=no 92 status_gsasl=no
93 status_mysql=no 93 status_mysql=no
94 status_pgsql=no 94 status_pgsql=no
...@@ -354,22 +354,31 @@ AH_BOTTOM( ...@@ -354,22 +354,31 @@ AH_BOTTOM(
354 # define MU_PATH_MAILDIR PATH_MAILDIR "/" 354 # define MU_PATH_MAILDIR PATH_MAILDIR "/"
355 #endif]) 355 #endif])
356 356
357 use_dbm=no 357 ##################################
358 # DBM Support
359 ##################################
360 AC_SUBST(DBMLIBS)
361 AC_SUBST(DBMLIB_DEPENDENCY)
362 AC_SUBST(DBMINCLUDES)
363
364 enable_dbm=no
365 disable_dbm=no
366
358 AC_ARG_WITH([gdbm], 367 AC_ARG_WITH([gdbm],
359 AC_HELP_STRING([--with-gdbm], 368 AC_HELP_STRING([--with-gdbm],
360 [use GNU DBM]), 369 [use GNU DBM]),
361 [ 370 [
362 case "${withval}" in 371 case "${withval}" in
363 yes) use_dbm=GDBM ;; 372 yes) enable_dbm="$enable_dbm GDBM";;
364 no) use_dbm=no ;; 373 no) disable_dbm="$disable_dbm GDBM";;
365 *) AC_MSG_ERROR(bad value ${withval} for --with-gdbm) ;; 374 *) AC_MSG_ERROR(bad value ${withval} for --with-gdbm) ;;
366 esac]) 375 esac])
367 376
368 ## Support --with-db2 for backward compatibility 377 ## Support --with-db2 for backward compatibility
369 if test "${with_db2+set}" = set; then 378 if test "${with_db2+set}" = set; then
370 case "${with_db2}" in 379 case "${with_db2}" in
371 yes) use_dbm=BDB2 ;; 380 yes) enable_dbm="$enable_dbm BDB2";;
372 no) use_dbm=no ;; 381 no) disable_dbm="$disable_dbm BDB2";;
373 *) AC_MSG_ERROR(bad value ${with_db2} for --with-db2) ;; 382 *) AC_MSG_ERROR(bad value ${with_db2} for --with-db2) ;;
374 esac 383 esac
375 fi 384 fi
...@@ -379,9 +388,9 @@ AC_ARG_WITH([berkeley-db], ...@@ -379,9 +388,9 @@ AC_ARG_WITH([berkeley-db],
379 [use Berkeley DB]), 388 [use Berkeley DB]),
380 [ 389 [
381 case "${withval}" in 390 case "${withval}" in
382 yes) use_dbm=BDB ;; 391 yes) enable_dbm="$enable_dbm BDB";;
383 no) use_dbm=no ;; 392 no) disable_dbm="$disable_dbm BDB";;
384 *) use_dbm=BDB="${withval}";; 393 *) enable_dbm="$enable_dbm BDB=${withval}";;
385 esac]) 394 esac])
386 395
387 AC_ARG_WITH([ndbm], 396 AC_ARG_WITH([ndbm],
...@@ -389,8 +398,8 @@ AC_ARG_WITH([ndbm], ...@@ -389,8 +398,8 @@ AC_ARG_WITH([ndbm],
389 [use NDBM]), 398 [use NDBM]),
390 [ 399 [
391 case "${withval}" in 400 case "${withval}" in
392 yes) use_dbm=NDBM ;; 401 yes) enable_dbm="$enable_dbm NDBM";;
393 no) use_dbm=no ;; 402 no) disable_dbm="$disable_dbm NDBM";;
394 *) AC_MSG_ERROR(bad value ${withval} for --with-ndbm) ;; 403 *) AC_MSG_ERROR(bad value ${withval} for --with-ndbm) ;;
395 esac]) 404 esac])
396 405
...@@ -399,11 +408,174 @@ AC_ARG_WITH([tokyocabinet], ...@@ -399,11 +408,174 @@ AC_ARG_WITH([tokyocabinet],
399 [use Tokyo Cabinet]), 408 [use Tokyo Cabinet]),
400 [ 409 [
401 case "${withval}" in 410 case "${withval}" in
402 yes) use_dbm=TC ;; 411 yes) enable_dbm="$enable_dbm TC";;
403 no) use_dbm=no ;; 412 no) disable_dbm="$disable_dbm TC";;
404 *) AC_MSG_ERROR(bad value ${withval} for --with-tokyocabinet) ;; 413 *) AC_MSG_ERROR(bad value ${withval} for --with-tokyocabinet) ;;
405 esac]) 414 esac])
406 415
416 dnl Check for DBM
417
418 AH_TEMPLATE([WITH_BDB],
419 [Define to the major version of Berkeley DB library to use])
420
421 status_bdb=no
422
423 ## Set the variable status_bdb to $1 if:
424 ##
425 ## 1. Function $3 is defined in the library $2
426 ## 2. Header file db.h is available
427 ##
428 ## Then check if the major version, minor version and patchlevel of the
429 ## library matches those from the header. If so, define WITH_BDB
430 ## to the version (i.e. $1 with all dots removed). Otherwise, report
431 ## an error and stop.
432 ##
433 check_bdb() {
434 ver=`echo $1 | tr -d '.'`
435 major=`expr $ver : '\(.\).*'`
436 status_bdb=no
437 AC_CHECK_LIB($2, $3,
438 [AC_CHECK_HEADERS(db.h)
439 if test $ac_cv_header_db_h = yes; then
440 DBMLIBS="$DBMLIBS -l$2"
441 MU_DB2_CURSOR
442 status_bdb="$1"
443 fi])
444 if test "$status_bdb" = no; then
445 :
446 else
447 save_LIBS=$LIBS
448 LIBS="$LIBS $DBMLIBS"
449 AC_RUN_IFELSE(
450 [AC_LANG_PROGRAM([#include "db.h"],
451 [int v_major, v_minor, v_patch;
452 db_version(&v_major, &v_minor, &v_patch);
453 return !(DB_VERSION_MAJOR == $major
454 && v_major == DB_VERSION_MAJOR
455 && v_minor == DB_VERSION_MINOR
456 && v_patch == DB_VERSION_PATCH);
457 ])],
458 [],
459 [status_bdb=no])
460 LIBS=$save_LIBS
461 if test "$status_bdb" != no; then
462 AC_DEFINE_UNQUOTED(WITH_BDB,$ver)
463 fi
464 fi
465 }
466
467 ## Check for the Berkeley DB library version $1, assuming Slackware-like
468 ## installation layout (header files in /usr/incude/db$vn and library named
469 ## libdb-$version.so, where $version is the library version and $vn is
470 ## $version with all dots removed.
471 ##
472 check_slackware_bdb() {
473 dir=db`echo $1|tr -d '.'`
474 save_CPPFLAGS=$CPPFLAGS
475 CPPFLAGS="$CPPFLAGS -I/usr/include/$dir"
476 check_bdb "$1" db-$1 db_create
477 CPPFLAGS=$save_CPPFLAGS
478 if test "$status_bdb" = "$1"; then
479 DBMINCLUDES="$DBMINCLUDES -I/usr/include/$dir"
480 status_dbm="$status_dbm,Berkeley DB v. $status_bdb"
481 fi
482 }
483
484 check_dbm_impl() {
485 case "$1" in
486 GDBM)
487 AC_CHECK_LIB(gdbm, gdbm_open,
488 [AC_CHECK_HEADERS(gdbm.h,
489 AC_DEFINE(WITH_GDBM,1,
490 [Enable use of GNU DBM library]))
491 DBMLIBS="$DBMLIBS -lgdbm"
492 status_dbm="$status_dbm,GDBM"]);;
493
494 BDB2) check_bdb 2 db db_open
495 test -n "$status_bdb" && status_dbm="$status_dbm,Berkeley DB v. $status_bdb";;
496
497 BDB) for version in 4 3 2
498 do
499 case $version in
500 4|3) func=db_create;;
501 2) func=db_open;;
502 esac
503 check_bdb $version db $func
504 if test "$status_bdb" != no; then
505 status_dbm="$status_dbm,Berkeley DB v. $status_bdb"
506 break;
507 fi
508 done;;
509
510 BDB=*)
511 name=`expr $use_dbm : 'BDB=\(.*\)'`
512 case $name in
513 [[0-9]]*) check_slackware_bdb $name;;
514 *) for version in 4 3 2
515 do
516 case $version in
517 4|3) func=db_create;;
518 2) func=db_open;;
519 esac
520 check_bdb $version $name $func
521 if test "$status_bdb" != no; then
522 status_dbm="$status_dbm,Berkeley DB v. $status_bdb"
523 break;
524 fi
525 done
526 ;;
527 esac
528 ;;
529
530 NDBM)
531 has_ndbm=no
532 AC_CHECK_HEADERS(ndbm.h,[has_ndbm=yes])
533 if test $has_ndbm = yes; then
534 AC_CHECK_FUNC(dbm_open,:,[has_ndbm=no])
535 if test $has_ndbm = no; then
536 AC_CHECK_LIB(ndbm, dbm_open,
537 [DBMLIBS="$DBMLIBS -lndbm"])
538 fi
539 fi
540 if test $has_ndbm = yes; then
541 AC_DEFINE(WITH_NDBM,1,[Enable use of NDBM])
542 status_dbm="$status_dbm,NDBM"
543 fi
544 ;;
545
546 TC)
547 AC_CHECK_LIB(tokyocabinet, tchdbnew,
548 [AC_CHECK_HEADERS(tchdb.h,
549 AC_DEFINE(WITH_TOKYOCABINET,1,
550 [Enable use of Tokyo Cabinet]))
551 DBMLIB_DEPENDENCY="$DBMLIB_DEPENDENCY -lz -lbz2 -lrt"
552 DBMLIBS="$DBMLIBS -ltokyocabinet"
553 status_dbm="$status_dbm,Tokyo Cabinet"]);;
554 esac
555 }
556
557 if test "$enable_dbm" = no; then
558 enable_dbm="GDBM BDB TC NDBM"
559 fi
560
561 for impl in $enable_dbm
562 do
563 if echo "$disable_dbm" | grep $impl >/dev/null; then
564 : # skip it
565 else
566 check_dbm_impl $impl
567 fi
568 done
569
570 if test -z "$status_dbm"; then
571 status_dbm=no
572 else
573 status_dbm=`echo "$status_dbm" | sed 's/^,//'`
574 AC_DEFINE([ENABLE_DBM], 1, [Define if DBM interface is compiled])
575 fi
576 AM_CONDITIONAL([MU_COND_DBM], [test "$status_dbm" != no])
577
578 ####################
407 AC_MSG_CHECKING(for log facility) 579 AC_MSG_CHECKING(for log facility)
408 log_facility="LOG_MAIL" 580 log_facility="LOG_MAIL"
409 AC_ARG_WITH([log-facility], 581 AC_ARG_WITH([log-facility],
...@@ -938,129 +1110,6 @@ AH_BOTTOM([ ...@@ -938,129 +1110,6 @@ AH_BOTTOM([
938 # define rl_completion_matches completion_matches 1110 # define rl_completion_matches completion_matches
939 #endif]) 1111 #endif])
940 1112
941 dnl Check for DBM
942
943 AH_TEMPLATE([WITH_BDB],
944 [Define to the major version of Berkeley DB library to use])
945
946 ## Set the variable status_dbm to $1 if:
947 ##
948 ## 1. Function $3 is defined in the library $2
949 ## 2. Header file db.h is available
950 ##
951 ## Then check if the major version, minor version and patchlevel of the
952 ## library matches those from the header. If so, define WITH_BDB
953 ## to the version (i.e. $1 with all dots removed). Otherwise, report
954 ## an error and stop.
955 ##
956 check_bdb() {
957 ver=`echo $1 | tr -d '.'`
958 major=`expr $ver : '\(.\).*'`
959 AC_CHECK_LIB($2, $3,
960 [AC_CHECK_HEADERS(db.h)
961 if test $ac_cv_header_db_h = yes; then
962 LIBS="$LIBS -l$2"
963 MU_DB2_CURSOR
964 status_dbm=$1
965 fi])
966 if test "$status_dbm" = no; then
967 :
968 else
969 AC_RUN_IFELSE(
970 [AC_LANG_PROGRAM([#include "db.h"],
971 [int v_major, v_minor, v_patch;
972 db_version(&v_major, &v_minor, &v_patch);
973 return !(DB_VERSION_MAJOR == $major
974 && v_major == DB_VERSION_MAJOR
975 && v_minor == DB_VERSION_MINOR
976 && v_patch == DB_VERSION_PATCH);
977 ])],
978 [],
979 [status_dbm=no])
980 if test "$status_dbm" != no; then
981 AC_DEFINE_UNQUOTED(WITH_BDB,$ver)
982 fi
983 fi
984 }
985
986 ## Check for the Berkeley DB library version $1, assuming Slackware-like
987 ## installation layout (header files in /usr/incude/db$vn and library named
988 ## libdb-$version.so, where $version is the library version and $vn is
989 ## $version with all dots removed.
990 ##
991 check_slackware_bdb() {
992 dir=db`echo $1|tr -d '.'`
993 save_CPPFLAGS=$CPPFLAGS
994 CPPFLAGS="$CPPFLAGS -I/usr/include/$dir"
995 check_bdb "$1" db-$1 db_create
996 CPPFLAGS=$save_CPPFLAGS
997 if test "$status_dbm" = "$1"; then
998 MU_COMMON_INCLUDES="$MU_COMMON_INCLUDES -I/usr/include/$dir"
999 fi
1000 }
1001
1002 case "$use_dbm" in
1003 GDBM)
1004 AC_CHECK_LIB(gdbm, gdbm_open,
1005 [AC_CHECK_HEADERS(gdbm.h,
1006 AC_DEFINE(WITH_GDBM,1,
1007 [Enable use of GNU DBM library]))
1008 LIBS="$LIBS -lgdbm"
1009 status_dbm="GDBM"]);;
1010
1011 BDB2) check_bdb 2 db db_open
1012 test -n "$status_dbm" && status_dbm="Berkeley DB v. $status_dbm";;
1013
1014 BDB) for version in 4 3 2
1015 do
1016 case $version in
1017 4|3) func=db_create;;
1018 2) func=db_open;;
1019 esac
1020 check_bdb $version db $func
1021 if test "$status_dbm" != no; then
1022 status_dbm="Berkeley DB v. $status_dbm"
1023 break;
1024 fi
1025 done;;
1026
1027 BDB=*)
1028 name=`expr $use_dbm : 'BDB=\(.*\)'`
1029 case $name in
1030 [[0-9]]*) check_slackware_bdb $name;;
1031 *) for version in 4 3 2
1032 do
1033 case $version in
1034 4|3) func=db_create;;
1035 2) func=db_open;;
1036 esac
1037 check_bdb $version $name $func
1038 if test "$status_dbm" != no; then
1039 status_dbm="Berkeley DB v. $status_dbm"
1040 break;
1041 fi
1042 done
1043 ;;
1044 esac
1045 ;;
1046
1047 NDBM)
1048 AC_CHECK_LIB(ndbm, dbm_open,
1049 [AC_CHECK_HEADERS(ndbm.h,
1050 AC_DEFINE(WITH_NDBM,1,
1051 [Enable use of NDBM]))
1052 LIBS="$LIBS -lndbm"
1053 status_dbm="NDBM"]);;
1054
1055 TC)
1056 AC_CHECK_LIB(tokyocabinet, tchdbnew,
1057 [AC_CHECK_HEADERS(tchdb.h,
1058 AC_DEFINE(WITH_TOKYOCABINET,1,
1059 [Enable use of Tokyo Cabinet]))
1060 LIBS="$LIBS -ltokyocabinet -lz -lbz2 -lrt"
1061 status_dbm="Tokyo Cabinet"]);;
1062 esac
1063
1064 AC_SUBST(POPAUTH) 1113 AC_SUBST(POPAUTH)
1065 if test "$status_dbm" != no; then 1114 if test "$status_dbm" != no; then
1066 POPAUTH='popauth$(EXEEXT)' 1115 POPAUTH='popauth$(EXEEXT)'
...@@ -1397,6 +1446,7 @@ AC_CONFIG_FILES([ ...@@ -1397,6 +1446,7 @@ AC_CONFIG_FILES([
1397 libmu_cpp/Makefile 1446 libmu_cpp/Makefile
1398 libmu_scm/Makefile 1447 libmu_scm/Makefile
1399 libmu_scm/mailutils/Makefile 1448 libmu_scm/mailutils/Makefile
1449 libmu_dbm/Makefile
1400 libmu_sieve/Makefile 1450 libmu_sieve/Makefile
1401 libmu_sieve/extensions/Makefile 1451 libmu_sieve/extensions/Makefile
1402 libproto/Makefile 1452 libproto/Makefile
......
...@@ -39,6 +39,7 @@ pkginclude_HEADERS = \ ...@@ -39,6 +39,7 @@ pkginclude_HEADERS = \
39 cidr.h\ 39 cidr.h\
40 cstr.h\ 40 cstr.h\
41 daemon.h\ 41 daemon.h\
42 dbm.h\
42 debug.h\ 43 debug.h\
43 diag.h\ 44 diag.h\
44 envelope.h\ 45 envelope.h\
......
...@@ -35,6 +35,7 @@ extern "C" { ...@@ -35,6 +35,7 @@ extern "C" {
35 #define MU_CTYPE_PUNCT 0x100 35 #define MU_CTYPE_PUNCT 0x100
36 #define MU_CTYPE_SPACE 0x200 36 #define MU_CTYPE_SPACE 0x200
37 #define MU_CTYPE_XLETR 0x400 37 #define MU_CTYPE_XLETR 0x400
38 #define MU_CTYPE_ENDLN 0x800
38 39
39 #define MU_C_TAB_MAX 128 40 #define MU_C_TAB_MAX 128
40 41
...@@ -56,6 +57,7 @@ extern int mu_c_tab[MU_C_TAB_MAX]; ...@@ -56,6 +57,7 @@ extern int mu_c_tab[MU_C_TAB_MAX];
56 #define mu_isalnum(c) mu_c_is_class (c, MU_CTYPE_ALPHA|MU_CTYPE_DIGIT) 57 #define mu_isalnum(c) mu_c_is_class (c, MU_CTYPE_ALPHA|MU_CTYPE_DIGIT)
57 #define mu_isascii(c) (((unsigned)c) < MU_C_TAB_MAX) 58 #define mu_isascii(c) (((unsigned)c) < MU_C_TAB_MAX)
58 #define mu_isblank(c) ((c) == ' ' || (c) == '\t') 59 #define mu_isblank(c) ((c) == ' ' || (c) == '\t')
60 #define mu_isendln(c) mu_c_is_class (c, MU_CTYPE_ENDLN)
59 61
60 #define mu_tolower(c) \ 62 #define mu_tolower(c) \
61 ({ int __c = (c); \ 63 ({ int __c = (c); \
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011
3 Free Software Foundation, Inc.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 3 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General
16 Public License along with this library. If not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #ifndef _MAILUTILS_DBM_H
20 #define _MAILUTILS_DBM_H
21
22 #include <mailutils/types.h>
23
24 struct mu_dbm_datum
25 {
26 char *mu_dptr; /* Data pointer */
27 size_t mu_dsize; /* Data size */
28 void *mu_data; /* Implementation-dependent data */
29 struct mu_dbm_impl *mu_sys; /* Pointer to implementation */
30 };
31
32 struct mu_dbm_impl
33 {
34 char *_dbm_name;
35 int (*_dbm_file_safety) (mu_dbm_file_t db, int mode, uid_t owner);
36 int (*_dbm_get_fd) (mu_dbm_file_t db, int *pag, int *dir);
37 int (*_dbm_open) (mu_dbm_file_t db, int flags, int mode);
38 int (*_dbm_close) (mu_dbm_file_t db);
39 int (*_dbm_fetch) (mu_dbm_file_t db, struct mu_dbm_datum const *key,
40 struct mu_dbm_datum *ret);
41 int (*_dbm_store) (mu_dbm_file_t db, struct mu_dbm_datum const *key,
42 struct mu_dbm_datum const *contents, int replace);
43 int (*_dbm_delete) (mu_dbm_file_t db,
44 struct mu_dbm_datum const *key);
45 int (*_dbm_firstkey) (mu_dbm_file_t db, struct mu_dbm_datum *ret);
46 int (*_dbm_nextkey) (mu_dbm_file_t db, struct mu_dbm_datum *ret);
47 void (*_dbm_datum_free) (struct mu_dbm_datum *datum);
48 char const *(*_dbm_strerror) (mu_dbm_file_t db);
49 };
50
51 extern mu_url_t mu_dbm_hint;
52
53 int mu_dbm_register (struct mu_dbm_impl *impl);
54 int mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db);
55 int mu_dbm_create (char *name, mu_dbm_file_t *db);
56 int mu_dbm_close (mu_dbm_file_t db);
57 void mu_dbm_datum_free (struct mu_dbm_datum *datum);
58 int mu_dbm_delete (mu_dbm_file_t db, struct mu_dbm_datum const *key);
59 void mu_dbm_destroy (mu_dbm_file_t *pdb);
60 int mu_dbm_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
61 struct mu_dbm_datum *ret);
62 int mu_dbm_store (mu_dbm_file_t db, struct mu_dbm_datum const *key,
63 struct mu_dbm_datum const *contents, int replace);
64 int mu_dbm_firstkey (mu_dbm_file_t db, struct mu_dbm_datum *ret);
65 int mu_dbm_nextkey (mu_dbm_file_t db, struct mu_dbm_datum *ret);
66 int mu_dbm_open (mu_dbm_file_t db, int flags, int mode);
67 int mu_dbm_safety_get_owner (mu_dbm_file_t db, uid_t *uid);
68 int mu_dbm_safety_get_flags (mu_dbm_file_t db, int *flags);
69 int mu_dbm_safety_set_owner (mu_dbm_file_t db, uid_t uid);
70 int mu_dbm_safety_set_flags (mu_dbm_file_t db, int flags);
71 int mu_dbm_safety_check (mu_dbm_file_t db);
72 char const *mu_dbm_strerror (mu_dbm_file_t db);
73 int mu_dbm_get_fd (mu_dbm_file_t db, int *pag, int *dir);
74
75 int mu_dbm_impl_iterator (mu_iterator_t *itr);
76
77 #endif
...@@ -21,6 +21,7 @@ sysinclude_HEADERS = \ ...@@ -21,6 +21,7 @@ sysinclude_HEADERS = \
21 attribute.h\ 21 attribute.h\
22 auth.h\ 22 auth.h\
23 body.h\ 23 body.h\
24 dbm.h\
24 debcat.h\ 25 debcat.h\
25 envelope.h\ 26 envelope.h\
26 file_stream.h\ 27 file_stream.h\
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifndef _MAILUTILS_SYS_DBM_H
19 # define _MAILUTILS_SYS_DBM_H
20
21 union _mu_dbm_errno
22 {
23 int n;
24 void *p;
25 };
26
27 struct _mu_dbm_file
28 {
29 char *db_name; /* Database name */
30 void *db_descr; /* Database descriptor */
31 int db_safety_flags; /* Safety checks */
32 uid_t db_owner; /* Database owner UID */
33 struct mu_dbm_impl *db_sys; /* Pointer to the database implementation */
34 union _mu_dbm_errno db_errno;
35 };
36
37 #endif
...@@ -75,7 +75,8 @@ struct _mu_assoc; ...@@ -75,7 +75,8 @@ struct _mu_assoc;
75 struct _mu_acl; 75 struct _mu_acl;
76 struct _mu_server; 76 struct _mu_server;
77 struct _mu_tcp_server; 77 struct _mu_tcp_server;
78 78 struct _mu_dbm_file;
79
79 struct mu_sockaddr; /* defined in mailutils/sockaddr.h */ 80 struct mu_sockaddr; /* defined in mailutils/sockaddr.h */
80 struct mu_cidr; /* defined in mailutils/cidr.h */ 81 struct mu_cidr; /* defined in mailutils/cidr.h */
81 82
...@@ -121,6 +122,7 @@ typedef struct _mu_opool *mu_opool_t; ...@@ -121,6 +122,7 @@ typedef struct _mu_opool *mu_opool_t;
121 typedef struct _mu_progmailer *mu_progmailer_t; 122 typedef struct _mu_progmailer *mu_progmailer_t;
122 typedef struct _mu_secret *mu_secret_t; 123 typedef struct _mu_secret *mu_secret_t;
123 typedef struct _mu_mime_io_buffer *mu_mime_io_buffer_t; 124 typedef struct _mu_mime_io_buffer *mu_mime_io_buffer_t;
125 typedef struct _mu_dbm_file *mu_dbm_file_t;
124 126
125 typedef void (*mu_onexit_t) (void*); 127 typedef void (*mu_onexit_t) (void*);
126 typedef unsigned int mu_debug_handle_t; 128 typedef unsigned int mu_debug_handle_t;
......
...@@ -24,7 +24,6 @@ libmuaux_a_SOURCES += \ ...@@ -24,7 +24,6 @@ libmuaux_a_SOURCES += \
24 daemon.c\ 24 daemon.c\
25 mailcap.c\ 25 mailcap.c\
26 manlock.c\ 26 manlock.c\
27 mu_dbm.c\
28 signal.c\ 27 signal.c\
29 strexit.c\ 28 strexit.c\
30 tcpwrap.c\ 29 tcpwrap.c\
...@@ -34,7 +33,6 @@ libmuaux_a_SOURCES += \ ...@@ -34,7 +33,6 @@ libmuaux_a_SOURCES += \
34 noinst_HEADERS +=\ 33 noinst_HEADERS +=\
35 mailcap.h\ 34 mailcap.h\
36 muaux.h\ 35 muaux.h\
37 mu_dbm.h\
38 tcpwrap.h 36 tcpwrap.h
39 37
40 EXTRA_DIST += utmp.c 38 EXTRA_DIST += utmp.c
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2002, 2006, 2007, 2009, 2010, 2011
3 Free Software Foundation, Inc.
4
5 GNU Mailutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 GNU Mailutils is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <stdlib.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <string.h>
28 #ifdef HAVE_STRINGS_H
29 # include <strings.h>
30 #endif
31 #include <errno.h>
32 #include <mailutils/errno.h>
33 #include <mailutils/stream.h>
34 #include <mu_dbm.h>
35 #include <xalloc.h>
36
37 int
38 mu_fcheck_perm (int fd, int mode)
39 {
40 struct stat st;
41
42 if (mode == 0)
43 return 0;
44 if (fstat (fd, &st) == -1)
45 {
46 if (errno == ENOENT)
47 return 0;
48 else
49 return 1;
50 }
51 if ((st.st_mode & 0777) != mode)
52 {
53 errno = MU_ERR_UNSAFE_PERMS;
54 return 1;
55 }
56 return 0;
57 }
58
59 int
60 mu_check_perm (const char *name, int mode)
61 {
62 struct stat st;
63
64 if (mode == 0)
65 return 0;
66 if (stat (name, &st) == -1)
67 {
68 if (errno == ENOENT)
69 return 0;
70 else
71 return 1;
72 }
73 if ((st.st_mode & 0777) != mode)
74 {
75 errno = MU_ERR_UNSAFE_PERMS;
76 return 1;
77 }
78 return 0;
79 }
80
81 static char *
82 make_db_name (const char *name, const char *suffix)
83 {
84 int nlen = strlen (name);
85 int slen = strlen (suffix);
86 char *p;
87
88 if (nlen > slen && strcmp (name + nlen - slen, suffix) == 0)
89 p = xstrdup (name);
90 else
91 {
92 p = xmalloc (strlen (name) + slen + 1);
93 strcat (strcpy (p, name), suffix);
94 }
95 return p;
96 }
97
98 #if defined(WITH_GDBM)
99
100 #define DB_SUFFIX ".db"
101
102 int
103 mu_dbm_stat (char *name, struct stat *sb)
104 {
105 int rc;
106 char *pfname = make_db_name (name, DB_SUFFIX);
107 rc = stat (pfname, sb);
108 free (pfname);
109 return rc;
110 }
111
112 int
113 mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode)
114 {
115 int f;
116 char *pfname = make_db_name (name, DB_SUFFIX);
117
118 if (mu_check_perm (pfname, mode))
119 {
120 free (pfname);
121 return -1;
122 }
123
124 switch (flags)
125 {
126 case MU_STREAM_CREAT:
127 f = GDBM_NEWDB;
128 break;
129
130 case MU_STREAM_READ:
131 f = GDBM_READER;
132 break;
133
134 case MU_STREAM_RDWR:
135 f = GDBM_WRCREAT;
136 break;
137
138 default:
139 free (pfname);
140 errno = EINVAL;
141 return 1;
142 }
143 *db = gdbm_open (pfname, 512, f, mode, NULL);
144 free (pfname);
145 return *db == NULL;
146 }
147
148 int
149 mu_dbm_close (DBM_FILE db)
150 {
151 gdbm_close(db);
152 return 0;
153 }
154
155 int
156 mu_dbm_fetch (DBM_FILE db, DBM_DATUM key, DBM_DATUM *ret)
157 {
158 *ret = gdbm_fetch (db, key);
159 return ret->dptr == NULL;
160 }
161
162 int
163 mu_dbm_delete (DBM_FILE db, DBM_DATUM key)
164 {
165 return gdbm_delete (db, key);
166 }
167
168 int
169 mu_dbm_insert (DBM_FILE db, DBM_DATUM key, DBM_DATUM contents, int replace)
170 {
171 return gdbm_store (db, key, contents,
172 replace ? GDBM_REPLACE : GDBM_INSERT);
173 }
174
175 DBM_DATUM
176 mu_dbm_firstkey (DBM_FILE db)
177 {
178 return gdbm_firstkey (db);
179 }
180
181 DBM_DATUM
182 mu_dbm_nextkey (DBM_FILE db, DBM_DATUM key)
183 {
184 return gdbm_nextkey (db, key);
185 }
186
187 void
188 mu_dbm_datum_free (DBM_DATUM *datum)
189 {
190 void *ptr = MU_DATUM_PTR (*datum);
191 if (ptr)
192 free (ptr);
193 MU_DATUM_PTR (*datum) = 0;
194 }
195
196 #elif defined(WITH_BDB)
197
198 #define DB_SUFFIX ".db"
199
200 int
201 mu_dbm_stat (char *name, struct stat *sb)
202 {
203 int rc;
204 char *pfname = make_db_name (name, DB_SUFFIX);
205 rc = stat (pfname, sb);
206 free (pfname);
207 return rc;
208 }
209
210 int
211 mu_dbm_open (char *name, DBM_FILE *dbm, int flags, int mode)
212 {
213 int f, rc;
214 DB *db;
215 char *pfname = make_db_name (name, DB_SUFFIX);
216
217 if (mu_check_perm (pfname, mode))
218 {
219 free (pfname);
220 errno = MU_ERR_UNSAFE_PERMS;
221 return -1;
222 }
223
224 switch (flags)
225 {
226 case MU_STREAM_CREAT:
227 f = DB_CREATE|DB_TRUNCATE;
228 break;
229
230 case MU_STREAM_READ:
231 f = DB_RDONLY;
232 break;
233
234 case MU_STREAM_RDWR:
235 f = DB_CREATE;
236 break;
237
238 default:
239 free (pfname);
240 errno = EINVAL;
241 return -1;
242 }
243
244 #if WITH_BDB == 2
245 rc = db_open (pfname, DB_HASH, f, mode, NULL, NULL, &db);
246 #else
247 rc = db_create (&db, NULL, 0);
248 if (rc != 0 || db == NULL)
249 return rc;
250 # if DB_VERSION_MAJOR == 3
251 rc = db->open (db, pfname, NULL, DB_HASH, f, mode);
252 # else
253 rc = db->open (db, NULL, pfname, NULL, DB_HASH, f, mode);
254 # endif
255 #endif
256
257 free (pfname);
258 if (rc)
259 return -1;
260
261 *dbm = malloc (sizeof **dbm);
262 if (!*dbm)
263 {
264 db->close (db, 0);
265 errno = ENOMEM;
266 return -1;
267 }
268 (*dbm)->db = db;
269 (*dbm)->dbc = NULL;
270 return 0;
271 }
272
273 int
274 mu_dbm_close (DBM_FILE db)
275 {
276 db->db->close (db->db, 0);
277 free (db);
278 return 0;
279 }
280
281 int
282 mu_dbm_fetch (DBM_FILE db, DBM_DATUM key, DBM_DATUM *ret)
283 {
284 return db->db->get (db->db, NULL, &key, ret, 0);
285 }
286
287 int
288 mu_dbm_delete (DBM_FILE db, DBM_DATUM key)
289 {
290 return db->db->del (db->db, NULL, &key, 0);
291 }
292
293 int
294 mu_dbm_insert (DBM_FILE db, DBM_DATUM key, DBM_DATUM contents, int replace)
295 {
296 /*FIXME: replace unused*/
297 return db->db->put (db->db, NULL, &key, &contents, 0);
298 }
299
300 DBM_DATUM
301 mu_dbm_firstkey (DBM_FILE db)
302 {
303 DBT key, data;
304 int ret;
305
306 memset (&key, 0, sizeof key);
307 memset (&data, 0, sizeof data);
308
309 if (!db->dbc)
310 {
311 if (db->db->cursor (db->db, NULL, &db->dbc BDB2_CURSOR_LASTARG) != 0)
312 return key;
313 }
314
315 if ((ret = db->dbc->c_get (db->dbc, &key, &data, DB_FIRST)) != 0)
316 {
317 key.data = NULL;
318 key.size = 0;
319 if (ret == DB_NOTFOUND)
320 errno = MU_ERR_NOENT;
321 else
322 errno = ret;
323 }
324 return key;
325 }
326
327 DBM_DATUM
328 mu_dbm_nextkey (DBM_FILE db, DBM_DATUM pkey /*unused*/)
329 {
330 DBT key, data;
331 int ret;
332
333 memset (&key, 0, sizeof key);
334 memset (&data, 0, sizeof data);
335
336 if (!db->dbc)
337 return key;
338
339 if ((ret = db->dbc->c_get (db->dbc, &key, &data, DB_NEXT)) != 0)
340 {
341 key.data = NULL;
342 key.size = 0;
343 if (ret == DB_NOTFOUND)
344 errno = MU_ERR_NOENT;
345 else
346 errno = ret;
347 }
348 return key;
349 }
350
351 void
352 mu_dbm_datum_free (DBM_DATUM *datum)
353 {
354 /* empty */
355 }
356
357 #elif defined(WITH_NDBM)
358
359 #define DB_SUFFIX ".pag"
360
361 int
362 mu_dbm_stat (char *name, struct stat *sb)
363 {
364 int rc;
365 char *pfname = make_db_name (name, DB_SUFFIX);
366 rc = stat (pfname, sb);
367 free (pfname);
368 return rc;
369 }
370
371 int
372 mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode)
373 {
374 int f;
375 char *pfname;
376
377 switch (flags)
378 {
379 case MU_STREAM_CREAT:
380 f = O_CREAT|O_TRUNC|O_RDWR;
381 break;
382
383 case MU_STREAM_READ:
384 f = O_RDONLY;
385 break;
386
387 case MU_STREAM_RDWR:
388 f = O_CREAT|O_RDWR;
389 break;
390
391 default:
392 errno = EINVAL;
393 return -1;
394 }
395 pfname = strip_suffix (name, DB_SUFFIX);
396 *db = dbm_open (pfname, f, mode);
397 free (pfname);
398 if (!*db)
399 return -1;
400
401 if (mu_fcheck_perm (dbm_dirfno (*db), mode)
402 || mu_fcheck_perm (dbm_pagfno (*db), mode))
403 {
404 dbm_close (*db);
405 return 1;
406 }
407
408 return 0;
409 }
410
411 int
412 mu_dbm_close (DBM_FILE db)
413 {
414 dbm_close (db);
415 return 0;
416 }
417
418 int
419 mu_dbm_fetch (DBM_FILE db, DBM_DATUM key, DBM_DATUM *ret)
420 {
421 *ret = dbm_fetch (db, key);
422 return ret->dptr == NULL;
423 }
424
425 int
426 mu_dbm_delete (DBM_FILE db, DBM_DATUM key)
427 {
428 return dbm_delete (db, key);
429 }
430
431 int
432 mu_dbm_insert (DBM_FILE db, DBM_DATUM key, DBM_DATUM contents, int replace)
433 {
434 return dbm_store (db, key, contents, replace ? DBM_REPLACE : DBM_INSERT);
435 }
436
437 DBM_DATUM
438 mu_dbm_firstkey (DBM_FILE db)
439 {
440 return dbm_firstkey (db);
441 }
442
443 DBM_DATUM
444 mu_dbm_nextkey (DBM_FILE db, DBM_DATUM key)
445 {
446 return dbm_nextkey (db, key);
447 }
448
449 void
450 mu_dbm_datum_free (DBM_DATUM *datum)
451 {
452 /* empty */
453 }
454
455 #elif defined(WITH_TOKYOCABINET)
456
457 #define DB_SUFFIX ".tch"
458
459 int
460 mu_dbm_stat (char *name, struct stat *sb)
461 {
462 int rc;
463 char *pfname = make_db_name (name, DB_SUFFIX);
464 rc = stat (pfname, sb);
465 free (pfname);
466 return rc;
467 }
468
469 int
470 mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode)
471 {
472 int f, ecode;
473 char *pfname = make_db_name (name, DB_SUFFIX);
474
475 if (mu_check_perm (pfname, mode))
476 {
477 free (pfname);
478 return -1;
479 }
480
481 switch (flags)
482 {
483 case MU_STREAM_CREAT:
484 f = HDBOWRITER | HDBOCREAT;
485 break;
486
487 case MU_STREAM_READ:
488 f = HDBOREADER;
489 break;
490
491 case MU_STREAM_RDWR:
492 f = HDBOREADER | HDBOWRITER;
493 break;
494
495 default:
496 free (pfname);
497 errno = EINVAL;
498 return 1;
499 }
500
501 *db = malloc (sizeof **db);
502 if (!*db)
503 {
504 errno = ENOMEM;
505 return -1;
506 }
507 (*db)->hdb = tchdbnew ();
508
509 if (!tchdbopen ((*db)->hdb, pfname, f))
510 ecode = tchdbecode ((*db)->hdb);
511
512 free (pfname);
513 return 0;
514 }
515
516 int
517 mu_dbm_close (DBM_FILE db)
518 {
519 tchdbclose (db->hdb);
520 tchdbdel (db->hdb);
521 return 0;
522 }
523
524 int
525 mu_dbm_fetch (DBM_FILE db, DBM_DATUM key, DBM_DATUM *ret)
526 {
527 ret->data = tchdbget (db->hdb, key.data, key.size, &ret->size);
528 return ret->data == NULL;
529 }
530
531 int
532 mu_dbm_delete (DBM_FILE db, DBM_DATUM key)
533 {
534 return !tchdbout (db->hdb, key.data, key.size);
535 }
536
537 int
538 mu_dbm_insert (DBM_FILE db, DBM_DATUM key, DBM_DATUM contents, int replace)
539 {
540 if (replace)
541 return !tchdbput (db->hdb, key.data, key.size, contents.data, contents.size);
542 else
543 return !tchdbputkeep (db->hdb, key.data, key.size,
544 contents.data, contents.size);
545 }
546
547 DBM_DATUM
548 mu_dbm_firstkey (DBM_FILE db)
549 {
550 DBM_DATUM key;
551 memset (&key, 0, sizeof key);
552
553 tchdbiterinit (db->hdb);
554 key.data = tchdbiternext (db->hdb, &key.size);
555 return key;
556 }
557
558 DBM_DATUM
559 mu_dbm_nextkey (DBM_FILE db, DBM_DATUM unused)
560 {
561 DBM_DATUM key;
562 memset (&key, 0, sizeof key);
563
564 key.data = tchdbiternext (db->hdb, &key.size);
565 return key;
566 }
567
568 void
569 mu_dbm_datum_free (DBM_DATUM *datum)
570 {
571 /* empty */
572 }
573
574 #endif
575
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 1999, 2000, 2001, 2002, 2005, 2007, 2009, 2010, 2011
3 Free Software Foundation, Inc.
4
5 GNU Mailutils is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
9
10 GNU Mailutils is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
17
18 #if defined(WITH_GDBM)
19
20 #include <gdbm.h>
21 #define USE_DBM
22 typedef GDBM_FILE DBM_FILE;
23 typedef datum DBM_DATUM;
24 #define MU_DATUM_SIZE(d) (d).dsize
25 #define MU_DATUM_PTR(d) (d).dptr
26
27 #elif defined(WITH_BDB)
28
29 #include <db.h>
30 #define USE_DBM
31
32 struct db2_file
33 {
34 DB *db;
35 DBC *dbc;
36 };
37
38 typedef struct db2_file *DBM_FILE;
39 typedef DBT DBM_DATUM;
40 #define MU_DATUM_SIZE(d) (d).size
41 #define MU_DATUM_PTR(d) (d).data
42
43 #elif defined(WITH_NDBM)
44
45 #include <ndbm.h>
46 #define USE_DBM
47 typedef DBM *DBM_FILE;
48 typedef datum DBM_DATUM;
49 #define MU_DATUM_SIZE(d) (d).dsize
50 #define MU_DATUM_PTR(d) (d).dptr
51
52 #elif defined(WITH_TOKYOCABINET)
53
54 #include <tcutil.h>
55 #include <tchdb.h>
56 #define USE_DBM
57
58 struct tokyocabinet_file
59 {
60 TCHDB *hdb;
61 };
62
63 struct tokyocabinet_datum {
64 void *data;
65 int size;
66 };
67
68 typedef struct tokyocabinet_file *DBM_FILE;
69 typedef struct tokyocabinet_datum DBM_DATUM;
70 #define MU_DATUM_SIZE(d) (d).size
71 #define MU_DATUM_PTR(d) (d).data
72
73 #endif
74
75 #ifdef USE_DBM
76 struct stat;
77 int mu_dbm_stat (char *name, struct stat *sb);
78 int mu_dbm_open (char *name, DBM_FILE *db, int flags, int mode);
79 int mu_dbm_close (DBM_FILE db);
80 int mu_dbm_fetch (DBM_FILE db, DBM_DATUM key, DBM_DATUM *ret);
81 int mu_dbm_insert (DBM_FILE db, DBM_DATUM key, DBM_DATUM contents, int replace);
82 int mu_dbm_delete (DBM_FILE db, DBM_DATUM key);
83 DBM_DATUM mu_dbm_firstkey (DBM_FILE db);
84 DBM_DATUM mu_dbm_nextkey (DBM_FILE db, DBM_DATUM key);
85 void mu_dbm_datum_free(DBM_DATUM *datum);
86 #endif /* USE_DBM */
87
88 int mu_fcheck_perm (int fd, int mode);
89 int mu_check_perm (const char *name, int mode);
...@@ -31,10 +31,10 @@ int mu_c_tab[MU_C_TAB_MAX] = { ...@@ -31,10 +31,10 @@ int mu_c_tab[MU_C_TAB_MAX] = {
31 MU_CTYPE_CNTRL, 31 MU_CTYPE_CNTRL,
32 MU_CTYPE_CNTRL, 32 MU_CTYPE_CNTRL,
33 MU_CTYPE_CNTRL|MU_CTYPE_SPACE, 33 MU_CTYPE_CNTRL|MU_CTYPE_SPACE,
34 MU_CTYPE_CNTRL|MU_CTYPE_SPACE|MU_CTYPE_ENDLN,
34 MU_CTYPE_CNTRL|MU_CTYPE_SPACE, 35 MU_CTYPE_CNTRL|MU_CTYPE_SPACE,
35 MU_CTYPE_CNTRL|MU_CTYPE_SPACE, 36 MU_CTYPE_CNTRL|MU_CTYPE_SPACE,
36 MU_CTYPE_CNTRL|MU_CTYPE_SPACE, 37 MU_CTYPE_CNTRL|MU_CTYPE_SPACE|MU_CTYPE_ENDLN,
37 MU_CTYPE_CNTRL|MU_CTYPE_SPACE,
38 MU_CTYPE_CNTRL, 38 MU_CTYPE_CNTRL,
39 MU_CTYPE_CNTRL, 39 MU_CTYPE_CNTRL,
40 MU_CTYPE_CNTRL, 40 MU_CTYPE_CNTRL,
......
1 ## This file is part of GNU Mailutils.
2 ## Copyright (C) 2011 Free Software Foundation, Inc.
3 ##
4 ## GNU Mailutils is free software; you can redistribute it and/or
5 ## modify it under the terms of the GNU General Public License as
6 ## published by the Free Software Foundation; either version 3, or (at
7 ## your option) any later version.
8 ##
9 ## GNU Mailutils is distributed in the hope that it will be useful, but
10 ## WITHOUT ANY WARRANTY; without even the implied warranty of
11 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ## General Public License for more details.
13 ##
14 ## You should have received a copy of the GNU General Public License
15 ## along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
16
17 INCLUDES = @MU_LIB_COMMON_INCLUDES@ @DBMINCLUDES@
18
19 lib_LTLIBRARIES = libmu_dbm.la
20
21 libmu_dbm_la_SOURCES = \
22 close.c\
23 create.c\
24 datumfree.c\
25 dbm.c\
26 delete.c\
27 destroy.c\
28 errstr.c\
29 fetch.c\
30 firstkey.c\
31 getfd.c\
32 nextkey.c\
33 open.c\
34 safety.c\
35 store.c\
36 berkeley.c\
37 gdbm.c\
38 ndbm.c
39
40 noinst_HEADERS = mudbm.h
41
42 libmu_dbm_la_LIBADD = ${MU_LIB_MAILUTILS} @MU_AUTHLIBS@ @DBMLIBS@ @LTLIBINTL@
43 libmu_dbm_la_LDFLAGS = -version-info @VI_CURRENT@:@VI_REVISION@:@VI_AGE@
44 libmu_dbm_la_DEPENDENCIES = @DBMLIB_DEPENDENCY@
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <stdlib.h>
22 #include <string.h>
23 #include <mailutils/types.h>
24 #include <mailutils/dbm.h>
25 #include <mailutils/util.h>
26 #include <mailutils/errno.h>
27 #include <mailutils/error.h>
28 #include <mailutils/stream.h>
29 #include "mudbm.h"
30
31 #if defined(WITH_BDB)
32 #include <db.h>
33
34 struct bdb_file
35 {
36 DB *db;
37 DBC *dbc;
38 };
39
40 static int
41 _bdb_file_safety (mu_dbm_file_t db, int mode, uid_t owner)
42 {
43 return mu_file_safety_check (db->db_name, mode, owner, NULL);
44 }
45
46 static int
47 _bdb_get_fd (mu_dbm_file_t db, int *pag, int *dir)
48 {
49 struct bdb_file *bdb_file = db->db_descr;
50 int rc = bdb_file->db->fd (bdb_file->db, pag);
51 if (rc)
52 {
53 db->db_errno.n = rc;
54 return MU_ERR_FAILURE;
55 }
56 if (dir)
57 *dir = *pag;
58 return 0;
59 }
60
61 static int
62 _bdb_open (mu_dbm_file_t mdb, int flags, int mode)
63 {
64 struct bdb_file *bdb_file;
65 int f, rc;
66 DB *db;
67
68 switch (flags)
69 {
70 case MU_STREAM_CREAT:
71 f = DB_CREATE|DB_TRUNCATE;
72 break;
73
74 case MU_STREAM_READ:
75 f = DB_RDONLY;
76 break;
77
78 case MU_STREAM_RDWR:
79 f = DB_CREATE;
80 break;
81
82 default:
83 return EINVAL;
84 }
85
86 #if WITH_BDB == 2
87 rc = db_open (db->db_name, DB_HASH, f, mode, NULL, NULL, &db);
88 #else
89 rc = db_create (&db, NULL, 0);
90 if (rc != 0 || db == NULL)
91 return MU_ERR_FAILURE;
92 # if DB_VERSION_MAJOR == 3
93 rc = db->open (db, mdb->db_name, NULL, DB_HASH, f, mode);
94 # else
95 rc = db->open (db, NULL, mdb->db_name, NULL, DB_HASH, f, mode);
96 # endif
97 #endif
98
99 if (rc)
100 return MU_ERR_FAILURE;
101
102 bdb_file = malloc (sizeof *bdb_file);
103 if (!bdb_file)
104 {
105 db->close (db, 0);
106 return ENOMEM;
107 }
108 bdb_file->db = db;
109 bdb_file->dbc = NULL;
110
111 mdb->db_descr = bdb_file;
112
113 return 0;
114 }
115
116 static int
117 _bdb_close (mu_dbm_file_t db)
118 {
119 if (db->db_descr)
120 {
121 struct bdb_file *bdb_file = db->db_descr;
122 bdb_file->db->close (bdb_file->db, 0);
123 free (bdb_file);
124 db->db_descr = NULL;
125 }
126 return 0;
127 }
128
129 static int
130 _bdb_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
131 struct mu_dbm_datum *ret)
132 {
133 DBT keydat, content;
134 struct bdb_file *bdb_file = db->db_descr;
135 int rc;
136
137 memset (&keydat, 0, sizeof keydat);
138 keydat.data = key->mu_dptr;
139 keydat.size = key->mu_dsize;
140 memset (&content, 0, sizeof content);
141 content.flags = DB_DBT_MALLOC;
142 rc = bdb_file->db->get (bdb_file->db, NULL, &keydat, &content, 0);
143 mu_dbm_datum_free (ret);
144 switch (rc)
145 {
146 case 0:
147 ret->mu_dptr = content.data;
148 ret->mu_dsize = content.size;
149 ret->mu_sys = db->db_sys;
150 break;
151
152 case DB_NOTFOUND:
153 db->db_errno.n = rc;
154 rc = MU_ERR_NOENT;
155 break;
156
157 default:
158 db->db_errno.n = rc;
159 rc = MU_ERR_FAILURE;
160 }
161 return rc;
162 }
163
164 static int
165 _bdb_store (mu_dbm_file_t db,
166 struct mu_dbm_datum const *key,
167 struct mu_dbm_datum const *contents,
168 int replace)
169 {
170 struct bdb_file *bdb_file = db->db_descr;
171 int rc;
172 DBT keydat, condat;
173
174 memset (&keydat, 0, sizeof keydat);
175 keydat.data = key->mu_dptr;
176 keydat.size = key->mu_dsize;
177
178 memset (&condat, 0, sizeof condat);
179 condat.data = contents->mu_dptr;
180 condat.size = contents->mu_dsize;
181
182 rc = bdb_file->db->put (bdb_file->db, NULL, &keydat, &condat,
183 replace ? 0 : DB_NOOVERWRITE);
184 db->db_errno.n = rc;
185 switch (rc)
186 {
187 case 0:
188 break;
189
190 case DB_KEYEXIST:
191 rc = MU_ERR_EXISTS;
192 break;
193
194 default:
195 rc = MU_ERR_FAILURE;
196 break;
197 }
198 return rc;
199 }
200
201 static int
202 _bdb_delete (mu_dbm_file_t db, struct mu_dbm_datum const *key)
203 {
204 DBT keydat;
205 struct bdb_file *bdb_file = db->db_descr;
206 int rc;
207
208 memset (&keydat, 0, sizeof keydat);
209 keydat.data = key->mu_dptr;
210 keydat.size = key->mu_dsize;
211 rc = bdb_file->db->del (bdb_file->db, NULL, &keydat, 0);
212 switch (rc)
213 {
214 case 0:
215 break;
216
217 case DB_NOTFOUND:
218 db->db_errno.n = rc;
219 rc = MU_ERR_NOENT;
220 break;
221
222 default:
223 db->db_errno.n = rc;
224 rc = MU_ERR_FAILURE;
225 }
226 return rc;
227 }
228
229 static int
230 _bdb_firstkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
231 {
232 struct bdb_file *bdb_file = db->db_descr;
233 int rc;
234 DBT key, dbt;
235
236 if (!bdb_file->dbc)
237 {
238 rc = bdb_file->db->cursor (bdb_file->db, NULL, &bdb_file->dbc
239 BDB2_CURSOR_LASTARG);
240 if (rc)
241 {
242 db->db_errno.n = rc;
243 return MU_ERR_FAILURE;
244 }
245 }
246 memset (&key, 0, sizeof key);
247 key.flags = DB_DBT_MALLOC;
248
249 memset (&dbt, 0, sizeof dbt);
250 dbt.flags = DB_DBT_MALLOC;
251 rc = bdb_file->dbc->c_get (bdb_file->dbc, &key, &dbt, DB_FIRST);
252 mu_dbm_datum_free (ret);
253 switch (rc)
254 {
255 case 0:
256 free (dbt.data); /* FIXME: cache it for the eventual fetch that can
257 follow */
258 ret->mu_dptr = key.data;
259 ret->mu_dsize = key.size;
260 ret->mu_sys = db->db_sys;
261 break;
262
263 case DB_NOTFOUND:
264 db->db_errno.n = rc;
265 rc = MU_ERR_NOENT;
266 break;
267
268 default:
269 db->db_errno.n = rc;
270 rc = MU_ERR_FAILURE;
271 }
272 return rc;
273 }
274
275 static int
276 _bdb_nextkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
277 {
278 struct bdb_file *bdb_file = db->db_descr;
279 int rc;
280 DBT key, dbt;
281
282 if (!bdb_file->dbc)
283 return MU_ERR_SEQ;
284
285 memset (&key, 0, sizeof key);
286 key.flags = DB_DBT_MALLOC;
287
288 memset (&dbt, 0, sizeof dbt);
289 dbt.flags = DB_DBT_MALLOC;
290 rc = bdb_file->dbc->c_get (bdb_file->dbc, &key, &dbt, DB_NEXT);
291 mu_dbm_datum_free (ret);
292 switch (rc)
293 {
294 case 0:
295 free (dbt.data); /* FIXME: cache it for the eventual fetch that can
296 follow */
297 ret->mu_dptr = key.data;
298 ret->mu_dsize = key.size;
299 ret->mu_sys = db->db_sys;
300 break;
301
302 case DB_NOTFOUND:
303 db->db_errno.n = rc;
304 rc = MU_ERR_NOENT;
305 break;
306
307 default:
308 db->db_errno.n = rc;
309 rc = MU_ERR_FAILURE;
310 }
311 return rc;
312 }
313
314 static void
315 _bdb_datum_free (struct mu_dbm_datum *datum)
316 {
317 free (datum->mu_dptr);
318 }
319
320 static char const *
321 _bdb_strerror (mu_dbm_file_t db)
322 {
323 return db_strerror (db->db_errno.n);
324 }
325
326 struct mu_dbm_impl _mu_dbm_bdb = {
327 "bdb",
328 _bdb_file_safety,
329 _bdb_get_fd,
330 _bdb_open,
331 _bdb_close,
332 _bdb_fetch,
333 _bdb_store,
334 _bdb_delete,
335 _bdb_firstkey,
336 _bdb_nextkey,
337 _bdb_datum_free,
338 _bdb_strerror
339 };
340 #endif
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 int
28 mu_dbm_close (mu_dbm_file_t db)
29 {
30 DBMSYSCK (db, _dbm_close);
31 if (!db->db_descr)
32 return 0;
33 return db->db_sys->_dbm_close (db);
34 }
35
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011
3 Free Software Foundation, Inc.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 3 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General
16 Public License along with this library. If not, see
17 <http://www.gnu.org/licenses/>. */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22 #include <unistd.h>
23 #include <stdlib.h>
24 #include <mailutils/types.h>
25 #include <mailutils/list.h>
26 #include <mailutils/url.h>
27 #include <mailutils/dbm.h>
28 #include <mailutils/errno.h>
29 #include <mailutils/util.h>
30 #include "mudbm.h"
31
32 int
33 mu_dbm_create (char *name, mu_dbm_file_t *db)
34 {
35 int rc;
36 mu_url_t url;
37
38 _mu_dbm_init ();
39 rc = mu_url_create_hint (&url, name, 0, mu_dbm_hint);
40 if (rc)
41 return rc;
42 rc = mu_dbm_create_from_url (url, db);
43 mu_url_destroy (&url);
44 return rc;
45 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <stdlib.h>
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 void
28 mu_dbm_datum_free (struct mu_dbm_datum *datum)
29 {
30 if (datum && datum->mu_data &&
31 datum->mu_sys && datum->mu_sys->_dbm_datum_free)
32 {
33 datum->mu_sys->_dbm_datum_free (datum);
34 datum->mu_data = NULL;
35 }
36 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <unistd.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <mailutils/types.h>
25 #include <mailutils/list.h>
26 #include <mailutils/url.h>
27 #include <mailutils/dbm.h>
28 #include <mailutils/util.h>
29 #include <mailutils/errno.h>
30 #include <mailutils/error.h>
31 #include <mailutils/nls.h>
32 #include <mailutils/mu_auth.h>
33 #include "mudbm.h"
34
35 static mu_list_t implist;
36 mu_url_t mu_dbm_hint;
37
38 static void
39 _implist_free (void *p)
40 {
41 struct mu_dbm_impl *impl = p;
42
43 free (impl->_dbm_name);
44 free (impl);
45 }
46
47 static int
48 _implist_cmp (const void *a, const void *b)
49 {
50 struct mu_dbm_impl const *ia = a;
51 struct mu_dbm_impl const *ib = b;
52
53 return strcmp (ia->_dbm_name, ib->_dbm_name);
54 }
55
56 void
57 _mu_dbm_init ()
58 {
59 int rc;
60
61 if (implist)
62 return;
63
64 rc = mu_list_create (&implist);
65 if (rc)
66 {
67 mu_error (_("cannot initialize DBM subsystem: %s"),
68 mu_strerror (rc));
69 abort ();
70 }
71 mu_list_set_destroy_item (implist, _implist_free);
72 mu_list_set_comparator (implist, _implist_cmp);
73 /* Add built-in entries */
74 #ifdef WITH_GDBM
75 mu_dbm_register (&_mu_dbm_gdbm);
76 #endif
77 #ifdef WITH_BDB
78 mu_dbm_register (&_mu_dbm_bdb);
79 #endif
80 #ifdef WITH_NDBM
81 mu_dbm_register (&_mu_dbm_ndbm);
82 #endif
83 #ifdef WITH_TOKYOCABINET
84 mu_dbm_register (&_mu_dbm_tokyokabinet);
85 #endif
86 if (!mu_dbm_hint)
87 {
88 struct mu_dbm_impl *impl;
89 char *urlbuf;
90
91 rc = mu_list_get (implist, 0, (void**) &impl);
92 if (rc)
93 {
94 mu_error (_("cannot initialize DBM hint: %s"),
95 mu_strerror (rc));
96 abort ();
97 }
98 urlbuf = malloc (strlen (impl->_dbm_name) + 4);
99 if (urlbuf)
100 {
101 strcpy (urlbuf, impl->_dbm_name);
102 strcat (urlbuf, "://");
103 rc = mu_url_create (&mu_dbm_hint, urlbuf);
104 free (urlbuf);
105 }
106 else
107 rc = ENOMEM;
108
109 if (rc)
110 {
111 mu_error (_("cannot initialize DBM hint: %s"),
112 mu_strerror (rc));
113 abort ();
114 }
115 }
116 }
117
118 int
119 mu_dbm_register (struct mu_dbm_impl *impl)
120 {
121 int rc;
122 struct mu_dbm_impl *ptr;
123
124 _mu_dbm_init ();
125 ptr = calloc (1, sizeof (*ptr));
126 if (!ptr)
127 return ENOMEM;
128 *ptr = *impl;
129 ptr->_dbm_name = strdup (impl->_dbm_name);
130 if (!ptr->_dbm_name)
131 {
132 free (ptr);
133 return ENOMEM;
134 }
135 rc = mu_list_append (implist, ptr);
136 if (rc)
137 _implist_free (ptr);
138 return rc;
139 }
140
141 int
142 mu_dbm_create_from_url (mu_url_t url, mu_dbm_file_t *db)
143 {
144 mu_dbm_file_t p;
145 int flags;
146 int rc;
147 const char *db_name;
148 struct mu_dbm_impl impl_key;
149 struct mu_dbm_impl *impl;
150 struct mu_auth_data *auth;
151 int safety_flags = 0;
152 uid_t owner_uid = getuid ();
153
154 _mu_dbm_init ();
155
156 mu_url_get_flags (url, &flags);
157 if ((flags & (MU_URL_HOST | MU_URL_PATH)) == (MU_URL_HOST | MU_URL_PATH))
158 return MU_ERR_URL_EXTRA_PARTS;
159 if (flags & MU_URL_HOST)
160 rc = mu_url_sget_host (url, &db_name);
161 else
162 rc = mu_url_sget_path (url, &db_name);
163 if (rc)
164 return rc;
165
166 rc = mu_url_sget_scheme (url, (const char**)&impl_key._dbm_name);
167 if (rc)
168 return rc;
169
170 rc = mu_list_locate (implist, (void *) &impl_key, (void **) &impl);
171 if (rc)
172 return rc;
173
174 if (flags & MU_URL_PARAM)
175 {
176 size_t fvc, i;
177 char **fvp;
178
179 mu_url_sget_fvpairs (url, &fvc, &fvp);
180 for (i = 0; i < fvc; i++)
181 {
182 const char *name = fvp[i];
183 int negate = 0;
184 int val;
185
186 if (*name == '-')
187 {
188 negate = 1;
189 name++;
190 }
191 else if (*name == '+')
192 name++;
193
194 if (strncmp (name, "owner", 5) == 0)
195 {
196 val = MU_FILE_SAFETY_OWNER_MISMATCH;
197 if (name[5] == '=')
198 {
199 auth = mu_get_auth_by_name (name + 6);
200 if (!auth)
201 {
202 char *end;
203 unsigned long uid;
204
205 errno = 0;
206 uid = strtoul (name + 6, &end, 0);
207 if (*end || errno)
208 return MU_ERR_NO_SUCH_USER;
209 auth = mu_get_auth_by_uid (uid);
210 if (!auth)
211 return MU_ERR_NO_SUCH_USER;
212 owner_uid = auth->uid;
213 mu_auth_data_free (auth);
214 }
215 }
216 else if (name[5])
217 return MU_ERR_URL_EXTRA_PARTS;//FIXME: better error code
218 }
219 else if (strcmp (name, "none") == 0)
220 {
221 safety_flags = negate ? MU_FILE_SAFETY_ALL : MU_FILE_SAFETY_NONE;
222 continue;
223 }
224 else if (strcmp (name, "all") == 0)
225 {
226 safety_flags = negate ? MU_FILE_SAFETY_NONE : MU_FILE_SAFETY_ALL;
227 continue;
228 }
229 else if (strcmp (name, "default") == 0)
230 {
231 val = DEFAULT_DBM_SAFETY_FLAGS;
232 }
233 else if (mu_file_safety_name_to_code (name, &val))
234 return MU_ERR_URL_EXTRA_PARTS;//FIXME: better error code
235
236 if (negate)
237 safety_flags &= ~val;
238 else
239 safety_flags |= val;
240 }
241 }
242
243 p = calloc (1, sizeof (*p));
244 if (!p)
245 return ENOMEM;
246 p->db_name = strdup (db_name);
247 if (!p->db_name)
248 {
249 free (p);
250 return ENOMEM;
251 }
252 p->db_safety_flags = safety_flags;
253 p->db_owner = owner_uid;
254 p->db_sys = impl;
255
256 *db = p;
257 return 0;
258 }
259
260 int
261 mu_dbm_impl_iterator (mu_iterator_t *itr)
262 {
263 _mu_dbm_init ();
264 return mu_list_get_iterator (implist, itr);
265 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 int
28 mu_dbm_delete (mu_dbm_file_t db, struct mu_dbm_datum const *key)
29 {
30 DBMSYSCK (db, _dbm_delete);
31 if (!db->db_descr)
32 return EINVAL;
33 return db->db_sys->_dbm_delete (db, key);
34 }
35
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <stdlib.h>
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 void
28 mu_dbm_destroy (mu_dbm_file_t *pdb)
29 {
30 if (pdb && *pdb)
31 {
32 mu_dbm_file_t db = *pdb;
33 if (db->db_descr)
34 mu_dbm_close (db);
35 free (db->db_name);
36 free (db);
37 *pdb = NULL;
38 }
39 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <stdlib.h>
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 char const *
28 mu_dbm_strerror (mu_dbm_file_t db)
29 {
30 if (!db)
31 return NULL;
32 if (!db->db_sys || !db->db_sys->_dbm_strerror)
33 return NULL;
34 if (!db->db_descr)
35 return mu_strerror (MU_ERR_NOT_OPEN);
36 return db->db_sys->_dbm_strerror (db);
37 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 int
28 mu_dbm_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
29 struct mu_dbm_datum *ret)
30 {
31 DBMSYSCK (db, _dbm_fetch);
32 if (!db->db_descr)
33 return EINVAL;
34 return db->db_sys->_dbm_fetch (db, key, ret);
35 }
36
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 int
28 mu_dbm_firstkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
29 {
30 DBMSYSCK (db, _dbm_firstkey);
31 if (!db->db_descr)
32 return EINVAL;
33 return db->db_sys->_dbm_firstkey (db, ret);
34 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <stdlib.h>
22 #include <string.h>
23 #include <mailutils/types.h>
24 #include <mailutils/dbm.h>
25 #include <mailutils/util.h>
26 #include <mailutils/errno.h>
27 #include <mailutils/error.h>
28 #include <mailutils/stream.h>
29 #include "mudbm.h"
30
31 #if defined(WITH_GDBM)
32 #include <gdbm.h>
33
34 struct gdbm_descr
35 {
36 GDBM_FILE file; /* GDBM file */
37 datum prev; /* Previous key for sequential access */
38 };
39
40 static int
41 _gdbm_file_safety (mu_dbm_file_t db, int mode, uid_t owner)
42 {
43 return mu_file_safety_check (db->db_name, mode, owner, NULL);
44 }
45
46 int
47 _gdbm_get_fd (mu_dbm_file_t db, int *pag, int *dir)
48 {
49 struct gdbm_descr *gd = db->db_descr;
50 *pag = gdbm_fdesc (gd->file);
51 if (dir)
52 *dir = *pag;
53 return 0;
54 }
55
56 static int
57 _gdbm_open (mu_dbm_file_t db, int flags, int mode)
58 {
59 int f;
60 struct gdbm_descr *gd;
61 GDBM_FILE file;
62
63 switch (flags)
64 {
65 case MU_STREAM_CREAT:
66 f = GDBM_NEWDB;
67 break;
68
69 case MU_STREAM_READ:
70 f = GDBM_READER;
71 break;
72
73 case MU_STREAM_RDWR:
74 f = GDBM_WRCREAT;
75 break;
76
77 default:
78 return EINVAL;
79 }
80 file = gdbm_open (db->db_name, 512, f, mode, NULL);
81 if (!file)
82 return MU_ERR_FAILURE;
83 gd = calloc (1, sizeof (*gd));
84 gd->file = file;
85 db->db_descr = gd;
86 return 0;
87 }
88
89 static int
90 _gdbm_close (mu_dbm_file_t db)
91 {
92 if (db->db_descr)
93 {
94 struct gdbm_descr *gd = db->db_descr;
95 gdbm_close (gd->file);
96 free (gd);
97 db->db_descr = NULL;
98 }
99 return 0;
100 }
101
102 static int
103 _gdbm_conv_datum (mu_dbm_file_t db, struct mu_dbm_datum *ret, datum content,
104 int copy)
105 {
106 if (copy)
107 {
108 ret->mu_dptr = malloc (content.dsize);
109 if (!ret->mu_dptr)
110 return errno;
111 memcpy (ret->mu_dptr, content.dptr, content.dsize);
112 }
113 else
114 {
115 ret->mu_dptr = content.dptr;
116 }
117 ret->mu_dsize = content.dsize;
118 ret->mu_sys = db->db_sys;
119 return 0;
120 }
121
122 static int
123 _gdbm_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
124 struct mu_dbm_datum *ret)
125 {
126 struct gdbm_descr *gd = db->db_descr;
127 int rc;
128 datum keydat, content;
129
130 keydat.dptr = key->mu_dptr;
131 keydat.dsize = key->mu_dsize;
132 gdbm_errno = 0;
133 content = gdbm_fetch (gd->file, keydat);
134 if (content.dptr == NULL)
135 {
136 if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
137 return MU_ERR_NOENT;
138 else
139 {
140 db->db_errno.n = gdbm_errno;
141 return MU_ERR_FAILURE;
142 }
143 }
144 mu_dbm_datum_free (ret);
145 rc = _gdbm_conv_datum (db, ret, content, 1);
146 if (rc)
147 {
148 free (content.dptr);
149 return rc;
150 }
151 return 0;
152 }
153
154 static int
155 _gdbm_store (mu_dbm_file_t db,
156 struct mu_dbm_datum const *key,
157 struct mu_dbm_datum const *contents,
158 int replace)
159 {
160 struct gdbm_descr *gd = db->db_descr;
161 datum keydat, condat;
162
163 keydat.dptr = key->mu_dptr;
164 keydat.dsize = key->mu_dsize;
165 condat.dptr = contents->mu_dptr;
166 condat.dsize = contents->mu_dsize;
167 switch (gdbm_store (gd->file, keydat, condat, replace))
168 {
169 case 0:
170 break;
171
172 case 1:
173 return MU_ERR_EXISTS;
174
175 case -1:
176 db->db_errno.n = gdbm_errno;
177 return MU_ERR_FAILURE;
178 }
179 return 0;
180 }
181
182 static int
183 _gdbm_delete (mu_dbm_file_t db, struct mu_dbm_datum const *key)
184 {
185 struct gdbm_descr *gd = db->db_descr;
186 datum keydat;
187
188 keydat.dptr = key->mu_dptr;
189 keydat.dsize = key->mu_dsize;
190 gdbm_errno = 0;
191 if (gdbm_delete (gd->file, keydat))
192 {
193 if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
194 return MU_ERR_NOENT;
195 else
196 {
197 db->db_errno.n = gdbm_errno;
198 return MU_ERR_FAILURE;
199 }
200 }
201 return 0;
202 }
203
204 static int
205 _gdbm_firstkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
206 {
207 struct gdbm_descr *gd = db->db_descr;
208 int rc;
209 datum key = gdbm_firstkey (gd->file);
210 if (key.dptr == NULL)
211 {
212 if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
213 return MU_ERR_NOENT;
214 else
215 {
216 db->db_errno.n = gdbm_errno;
217 return MU_ERR_FAILURE;
218 }
219 }
220 mu_dbm_datum_free (ret);
221 rc = _gdbm_conv_datum (db, ret, key, 0);
222 if (rc)
223 {
224 free (key.dptr);
225 return rc;
226 }
227 free (gd->prev.dptr);
228 gd->prev = key;
229 return 0;
230 }
231
232 static int
233 _gdbm_nextkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
234 {
235 struct gdbm_descr *gd = db->db_descr;
236 int rc;
237 datum key;
238
239 if (!gd->prev.dptr)
240 return MU_ERR_NOENT;
241 key = gdbm_nextkey (gd->file, gd->prev);
242 if (key.dptr == NULL)
243 {
244 if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
245 return MU_ERR_NOENT;
246 else
247 {
248 db->db_errno.n = gdbm_errno;
249 return MU_ERR_FAILURE;
250 }
251 }
252 mu_dbm_datum_free (ret);
253 rc = _gdbm_conv_datum (db, ret, key, 0);
254 if (rc)
255 {
256 free (key.dptr);
257 return rc;
258 }
259 free (gd->prev.dptr);
260 gd->prev = key;
261 return 0;
262 }
263
264 static void
265 _gdbm_datum_free (struct mu_dbm_datum *datum)
266 {
267 free (datum->mu_dptr);
268 }
269
270 static char const *
271 _gdbm_strerror (mu_dbm_file_t db)
272 {
273 return gdbm_strerror (db->db_errno.n);
274 }
275
276 struct mu_dbm_impl _mu_dbm_gdbm = {
277 "gdbm",
278 _gdbm_file_safety,
279 _gdbm_get_fd,
280 _gdbm_open,
281 _gdbm_close,
282 _gdbm_fetch,
283 _gdbm_store,
284 _gdbm_delete,
285 _gdbm_firstkey,
286 _gdbm_nextkey,
287 _gdbm_datum_free,
288 _gdbm_strerror
289 };
290 #endif
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 int
28 mu_dbm_get_fd (mu_dbm_file_t db, int *pag, int *dir)
29 {
30 DBMSYSCK (db, _dbm_get_fd);
31 if (!db->db_descr || !pag)
32 return EINVAL;
33 return db->db_sys->_dbm_get_fd (db, pag, dir);
34 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #include <mailutils/sys/dbm.h>
19
20 #define DBMSYSCK(db,meth) do \
21 { \
22 if (!(db)) \
23 return EINVAL; \
24 if (!(db)->db_descr) \
25 return MU_ERR_NOT_OPEN; \
26 if (!(db)->db_sys || !(db)->db_sys->meth) \
27 return ENOSYS; \
28 } \
29 while (0)
30
31 #define DEFAULT_DBM_SAFETY_FLAGS MU_FILE_SAFETY_ALL
32
33 #ifdef WITH_GDBM
34 extern struct mu_dbm_impl _mu_dbm_gdbm;
35 #endif
36 #ifdef WITH_BDB
37 extern struct mu_dbm_impl _mu_dbm_bdb;
38 #endif
39 #ifdef WITH_NDBM
40 extern struct mu_dbm_impl _mu_dbm_ndbm;
41 #endif
42 #ifdef WITH_TOKYOCABINET
43 extern struct mu_dbm_impl _mu_dbm_tokyokabinet;
44 #endif
45
46 void _mu_dbm_init (void);
47
48
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21 #include <fcntl.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <mailutils/types.h>
25 #include <mailutils/dbm.h>
26 #include <mailutils/util.h>
27 #include <mailutils/errno.h>
28 #include <mailutils/error.h>
29 #include <mailutils/stream.h>
30 #include <mailutils/io.h>
31 #include "mudbm.h"
32
33 #if defined(WITH_NDBM)
34 #include <ndbm.h>
35
36 static int
37 _ndbm_file_safety (mu_dbm_file_t db, int mode, uid_t owner)
38 {
39 int rc;
40 char *name;
41
42 rc = mu_asprintf (&name, "%s.pag", db->db_name);
43 if (rc)
44 return rc;
45 rc = mu_file_safety_check (name, mode, owner, NULL);
46 if (rc)
47 {
48 free (name);
49 return rc;
50 }
51
52 strcpy (name + strlen (name) - 3, "dir");
53 rc = mu_file_safety_check (name, mode, owner, NULL);
54 free (name);
55 return rc;
56 }
57
58 int
59 _ndbm_get_fd (mu_dbm_file_t db, int *pag, int *dir)
60 {
61 DBM *dbm = db->db_descr;
62 *pag = dbm_pagfno (dbm);
63 if (dir)
64 *dir = dbm_dirfno (dbm);
65 return 0;
66 }
67
68 static int
69 _ndbm_open (mu_dbm_file_t db, int flags, int mode)
70 {
71 int f;
72 DBM *dbm;
73
74 switch (flags)
75 {
76 case MU_STREAM_CREAT:
77 f = O_CREAT|O_TRUNC|O_RDWR;
78 break;
79
80 case MU_STREAM_READ:
81 f = O_RDONLY;
82 break;
83
84 case MU_STREAM_RDWR:
85 f = O_CREAT|O_RDWR;
86 break;
87
88 default:
89 errno = EINVAL;
90 return -1;
91 }
92 dbm = dbm_open (db->db_name, f, mode);
93 if (!dbm)
94 return MU_ERR_FAILURE;
95 db->db_descr = dbm;
96 return 0;
97 }
98
99 static int
100 _ndbm_close (mu_dbm_file_t db)
101 {
102 if (db->db_descr)
103 {
104 dbm_close ((DBM *) db->db_descr);
105 db->db_descr = NULL;
106 }
107 return 0;
108 }
109
110 static int
111 _ndbm_conv_datum (mu_dbm_file_t db, struct mu_dbm_datum *ret, datum content)
112 {
113 ret->mu_dptr = malloc (content.dsize);
114 if (!ret->mu_dptr)
115 return errno;
116 memcpy (ret->mu_dptr, content.dptr, content.dsize);
117 ret->mu_dsize = content.dsize;
118 ret->mu_sys = db->db_sys;
119 return 0;
120 }
121
122 static int
123 _ndbm_fetch (mu_dbm_file_t db, struct mu_dbm_datum const *key,
124 struct mu_dbm_datum *ret)
125 {
126 datum keydat, content;
127
128 keydat.dptr = key->mu_dptr;
129 keydat.dsize = key->mu_dsize;
130 errno = 0;
131 content = dbm_fetch (db->db_descr, keydat);
132 mu_dbm_datum_free (ret);
133 if (content.dptr == NULL)
134 return MU_ERR_NOENT;
135 return _ndbm_conv_datum (db, ret, content);
136 }
137
138 static int
139 _ndbm_store (mu_dbm_file_t db,
140 struct mu_dbm_datum const *key,
141 struct mu_dbm_datum const *contents,
142 int replace)
143 {
144 DBM *dbm = db->db_descr;
145 datum keydat, condat;
146
147 keydat.dptr = key->mu_dptr;
148 keydat.dsize = key->mu_dsize;
149 condat.dptr = contents->mu_dptr;
150 condat.dsize = contents->mu_dsize;
151 errno = 0;
152 switch (dbm_store (dbm, keydat, condat,
153 replace ? DBM_REPLACE : DBM_INSERT))
154 {
155 case 0:
156 break;
157
158 case 1:
159 return MU_ERR_EXISTS;
160
161 case -1:
162 db->db_errno.n = errno;
163 return MU_ERR_FAILURE;
164 }
165 return 0;
166 }
167
168 static int
169 _ndbm_delete (mu_dbm_file_t db, struct mu_dbm_datum const *key)
170 {
171 DBM *dbm = db->db_descr;
172 datum keydat;
173
174 keydat.dptr = key->mu_dptr;
175 keydat.dsize = key->mu_dsize;
176 errno = 0;
177 switch (dbm_delete (dbm, keydat))
178 {
179 case 0:
180 break;
181
182 case 1:
183 return MU_ERR_NOENT;
184
185 case -1:
186 db->db_errno.n = errno;
187 return MU_ERR_FAILURE;
188 }
189 return 0;
190 }
191
192 static int
193 _ndbm_firstkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
194 {
195 DBM *dbm = db->db_descr;
196 datum keydat;
197
198 errno = 0;
199 keydat = dbm_firstkey (dbm);
200 if (keydat.dptr == NULL)
201 return MU_ERR_NOENT;
202 return _ndbm_conv_datum (db, ret, keydat);
203 }
204
205 static int
206 _ndbm_nextkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
207 {
208 DBM *dbm = db->db_descr;
209 datum keydat;
210
211 keydat = dbm_nextkey (dbm);
212 if (keydat.dptr == NULL)
213 return MU_ERR_NOENT;
214 return _ndbm_conv_datum (db, ret, keydat);
215 }
216
217 static void
218 _ndbm_datum_free (struct mu_dbm_datum *datum)
219 {
220 free (datum->mu_dptr);
221 }
222
223 static char const *
224 _ndbm_strerror (mu_dbm_file_t db)
225 {
226 return strerror (db->db_errno.n);
227 }
228
229 struct mu_dbm_impl _mu_dbm_ndbm = {
230 "ndbm",
231 _ndbm_file_safety,
232 _ndbm_get_fd,
233 _ndbm_open,
234 _ndbm_close,
235 _ndbm_fetch,
236 _ndbm_store,
237 _ndbm_delete,
238 _ndbm_firstkey,
239 _ndbm_nextkey,
240 _ndbm_datum_free,
241 _ndbm_strerror
242 };
243
244 #endif
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 int
28 mu_dbm_nextkey (mu_dbm_file_t db, struct mu_dbm_datum *ret)
29 {
30 DBMSYSCK (db, _dbm_nextkey);
31 if (!db->db_descr)
32 return EINVAL;
33 return db->db_sys->_dbm_nextkey (db, ret);
34 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 int
28 mu_dbm_open (mu_dbm_file_t db, int flags, int mode)
29 {
30 if (!db)
31 return EINVAL;
32 if (!db->db_sys || !db->db_sys->_dbm_open)
33 return ENOSYS;
34 return db->db_sys->_dbm_open (db, flags, mode);
35 }
36
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 int
28 mu_dbm_safety_set_owner (mu_dbm_file_t db, uid_t uid)
29 {
30 if (!db)
31 return EINVAL;
32 db->db_owner = uid;
33 return 0;
34 }
35
36 int
37 mu_dbm_safety_get_owner (mu_dbm_file_t db, uid_t *uid)
38 {
39 if (!db)
40 return EINVAL;
41 *uid = db->db_owner;
42 return 0;
43 }
44
45 int
46 mu_dbm_safety_set_flags (mu_dbm_file_t db, int flags)
47 {
48 if (!db)
49 return EINVAL;
50 db->db_safety_flags = flags;
51 return 0;
52 }
53
54 int
55 mu_dbm_safety_get_flags (mu_dbm_file_t db, int *flags)
56 {
57 if (!db)
58 return EINVAL;
59 *flags = db->db_safety_flags;
60 return 0;
61 }
62
63 int
64 mu_dbm_safety_check (mu_dbm_file_t db)
65 {
66 if (!db)
67 return EINVAL;
68 if (!db->db_sys || !db->db_sys->_dbm_file_safety)
69 return ENOSYS;
70 return db->db_sys->_dbm_file_safety (db, db->db_safety_flags,
71 db->db_owner);
72 }
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2011 Free Software Foundation, Inc.
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 3 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General
15 Public License along with this library. If not, see
16 <http://www.gnu.org/licenses/>. */
17
18 #ifdef HAVE_CONFIG_H
19 # include <config.h>
20 #endif
21
22 #include <mailutils/types.h>
23 #include <mailutils/dbm.h>
24 #include <mailutils/errno.h>
25 #include "mudbm.h"
26
27 int
28 mu_dbm_store (mu_dbm_file_t db, struct mu_dbm_datum const *key,
29 struct mu_dbm_datum const *contents, int replace)
30 {
31 DBMSYSCK (db, _dbm_store);
32 if (!db->db_descr)
33 return EINVAL;
34 return db->db_sys->_dbm_store (db, key, contents, replace);
35 }
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
36 #include <string.h> 36 #include <string.h>
37 #include <signal.h> 37 #include <signal.h>
38 #include <regex.h> 38 #include <regex.h>
39 #include <mu_dbm.h>
40 #include <mailutils/sieve.h> 39 #include <mailutils/sieve.h>
41 #include <mailutils/mu_auth.h> 40 #include <mailutils/mu_auth.h>
42 41
......
...@@ -46,6 +46,8 @@ maidag_LDADD = \ ...@@ -46,6 +46,8 @@ maidag_LDADD = \
46 @MU_AUTHLIBS@\ 46 @MU_AUTHLIBS@\
47 ${MU_LIB_MAILUTILS} \ 47 ${MU_LIB_MAILUTILS} \
48 @MU_COMMON_LIBRARIES@\ 48 @MU_COMMON_LIBRARIES@\
49 ../libmu_dbm/libmu_dbm.la\
50 @DBMLIBS@\
49 @TCPWRAP_LIBRARIES@ 51 @TCPWRAP_LIBRARIES@
50 52
51 INCLUDES = -I${top_srcdir} @MU_APP_COMMON_INCLUDES@ @GUILE_INCLUDES@ \ 53 INCLUDES = -I${top_srcdir} @MU_APP_COMMON_INCLUDES@ @GUILE_INCLUDES@ \
......
...@@ -457,7 +457,7 @@ struct mu_cfg_param maidag_cfg_param[] = { ...@@ -457,7 +457,7 @@ struct mu_cfg_param maidag_cfg_param[] = {
457 { "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, 0, NULL, 457 { "exit-quota-tempfail", mu_cfg_bool, &ex_quota_tempfail, 0, NULL,
458 N_("Indicate temporary failure if the recipient is over his mail quota.") 458 N_("Indicate temporary failure if the recipient is over his mail quota.")
459 }, 459 },
460 #ifdef USE_DBM 460 #ifdef ENABLE_DBM
461 { "quota-db", mu_cfg_string, &quotadbname, 0, NULL, 461 { "quota-db", mu_cfg_string, &quotadbname, 0, NULL,
462 N_("Name of DBM quota database file."), 462 N_("Name of DBM quota database file."),
463 N_("file") }, 463 N_("file") },
......
...@@ -86,10 +86,9 @@ ...@@ -86,10 +86,9 @@
86 #include <mailutils/server.h> 86 #include <mailutils/server.h>
87 #include <mailutils/cctype.h> 87 #include <mailutils/cctype.h>
88 #include <mailutils/io.h> 88 #include <mailutils/io.h>
89 #include <mailutils/dbm.h>
89 90
90 #include <mu_dbm.h> 91 #if defined (ENABLE_DBM) || defined (USE_SQL)
91
92 #if defined (USE_DBM) || defined (USE_SQL)
93 # define USE_MAILBOX_QUOTAS 1 92 # define USE_MAILBOX_QUOTAS 1
94 #endif 93 #endif
95 94
......
...@@ -64,64 +64,85 @@ fail_retrieve_quota (char *name, mu_off_t *quota) ...@@ -64,64 +64,85 @@ fail_retrieve_quota (char *name, mu_off_t *quota)
64 return RETR_FAILURE; 64 return RETR_FAILURE;
65 } 65 }
66 66
67 #ifdef USE_DBM 67 #ifdef ENABLE_DBM
68 int 68 int
69 dbm_retrieve_quota (char *name, mu_off_t *quota) 69 dbm_retrieve_quota (char *name, mu_off_t *quota)
70 { 70 {
71 DBM_FILE db; 71 mu_dbm_file_t db;
72 DBM_DATUM named, contentd; 72 struct mu_dbm_datum named, contentd;
73 char buffer[64]; 73 char buffer[64];
74 int unlimited = 0; 74 int unlimited = 0;
75 int rc; 75 int rc;
76 76
77 if (!quotadbname) 77 if (!quotadbname)
78 return RETR_FAILURE; 78 return RETR_FAILURE;
79 79
80 if (mu_dbm_open (quotadbname, &db, MU_STREAM_READ, 0600)) 80 rc = mu_dbm_create (quotadbname, &db);
81 if (rc)
82 {
83 mu_error (_("unable to create quota db"));
84 return RETR_FAILURE;
85 }
86
87 rc = mu_dbm_safety_check (db);
88 if (rc && rc != ENOENT)
81 { 89 {
82 mu_error (_("cannot open file %s: %s"), quotadbname, mu_strerror (errno)); 90 mu_error (_("quota db fails safety check: %s"),
91 mu_strerror (rc));
92 mu_dbm_destroy (&db);
93 return RETR_FAILURE;
94 }
95
96 rc = mu_dbm_open (db, MU_STREAM_READ, 0600);
97 if (rc)
98 {
99 mu_error (_("cannot open file %s: %s"),
100 quotadbname, mu_strerror (rc));
101 mu_dbm_destroy (&db);
83 return RETR_FAILURE; 102 return RETR_FAILURE;
84 } 103 }
85 104
86 memset (&named, 0, sizeof named); 105 memset (&named, 0, sizeof named);
87 memset (&contentd, 0, sizeof contentd); 106 memset (&contentd, 0, sizeof contentd);
88 MU_DATUM_PTR (named) = name; 107 named.mu_dptr = name;
89 MU_DATUM_SIZE (named) = strlen (name); 108 named.mu_dsize = strlen (name);
90 rc = mu_dbm_fetch (db, named, &contentd); 109 rc = mu_dbm_fetch (db, &named, &contentd);
91 if (rc || !MU_DATUM_PTR (contentd)) 110 if (rc)
92 { 111 {
93 /* User not in database, try default quota */ 112 /* User not in database, try default quota */
94 memset (&named, 0, sizeof named); 113 mu_dbm_datum_free (&named);
95 MU_DATUM_PTR (named) = "DEFAULT"; 114 named.mu_dptr = "DEFAULT";
96 MU_DATUM_SIZE (named) = strlen ("DEFAULT"); 115 named.mu_dsize = strlen ("DEFAULT");
97 rc = mu_dbm_fetch (db, named, &contentd); 116 rc = mu_dbm_fetch (db, &named, &contentd);
98 if (rc) 117 if (rc == MU_ERR_NOENT)
99 { 118 {
100 /*mu_error (_("can't fetch data: %s"), strerror (rc));*/ 119 mu_dbm_destroy (&db);
120 return RETR_FAILURE;
121 }
122 else if (rc)
123 {
124 mu_error (_("can't fetch data: %s"), mu_dbm_strerror (db));
125 mu_dbm_destroy (&db);
101 return RETR_FAILURE; 126 return RETR_FAILURE;
102 } 127 }
103 if (!MU_DATUM_PTR (contentd))
104 return RETR_FAILURE;
105 } 128 }
106 129
107 if (mu_c_strncasecmp("none", 130 if (mu_c_strncasecmp("none", contentd.mu_dptr, contentd.mu_dsize) == 0)
108 MU_DATUM_PTR (contentd),
109 MU_DATUM_SIZE (contentd)) == 0)
110 unlimited = 1; 131 unlimited = 1;
111 else if (MU_DATUM_SIZE (contentd) > sizeof(buffer)-1) 132 else if (contentd.mu_dsize > sizeof (buffer) - 1)
112 { 133 {
113 mu_error (ngettext ("mailbox quota for `%s' is too big: %d digit", 134 mu_error (ngettext ("mailbox quota for `%s' is too big: %d digit",
114 "mailbox quota for `%s' is too big: %d digits", 135 "mailbox quota for `%s' is too big: %d digits",
115 MU_DATUM_SIZE (contentd)), 136 contentd.mu_dsize),
116 name, MU_DATUM_SIZE (contentd)); 137 name, contentd.mu_dsize);
117 *quota = groupquota; 138 *quota = groupquota;
118 } 139 }
119 else 140 else
120 { 141 {
121 char *p; 142 char *p;
122 143
123 strncpy(buffer, MU_DATUM_PTR (contentd), MU_DATUM_SIZE (contentd)); 144 strncpy (buffer, contentd.mu_dptr, contentd.mu_dsize);
124 buffer[MU_DATUM_SIZE (contentd)] = 0; 145 buffer[contentd.mu_dsize] = 0;
125 *quota = strtoul (buffer, &p, 0); 146 *quota = strtoul (buffer, &p, 0);
126 if (get_size (buffer, quota, &p)) 147 if (get_size (buffer, quota, &p))
127 { 148 {
...@@ -129,8 +150,9 @@ dbm_retrieve_quota (char *name, mu_off_t *quota) ...@@ -129,8 +150,9 @@ dbm_retrieve_quota (char *name, mu_off_t *quota)
129 *quota = groupquota; 150 *quota = groupquota;
130 } 151 }
131 } 152 }
132 153
133 mu_dbm_close (db); 154 mu_dbm_datum_free (&contentd);
155 mu_dbm_destroy (&db);
134 156
135 return unlimited ? RETR_UNLIMITED : RETR_OK; 157 return unlimited ? RETR_UNLIMITED : RETR_OK;
136 } 158 }
......
...@@ -32,9 +32,17 @@ else ...@@ -32,9 +32,17 @@ else
32 IDLE_MODULES+=imap.c 32 IDLE_MODULES+=imap.c
33 endif 33 endif
34 34
35 if MU_COND_DBM
36 DBM_C=dbm.c
37 LIBMU_DBM=../libmu_dbm/libmu_dbm.la
38 else
39 IDLE_MODULES+=dbm.c
40 endif
41
35 MODULES = \ 42 MODULES = \
36 acl.c\ 43 acl.c\
37 cflags.c\ 44 cflags.c\
45 $(DBM_C)\
38 $(IMAP_C)\ 46 $(IMAP_C)\
39 filter.c\ 47 filter.c\
40 flt2047.c\ 48 flt2047.c\
...@@ -67,6 +75,7 @@ mu_LDADD = \ ...@@ -67,6 +75,7 @@ mu_LDADD = \
67 ${MU_LIB_AUTH}\ 75 ${MU_LIB_AUTH}\
68 @MU_AUTHLIBS@\ 76 @MU_AUTHLIBS@\
69 ${MU_LIB_MAILUTILS}\ 77 ${MU_LIB_MAILUTILS}\
78 ${LIBMU_DBM} @DBMLIBS@\
70 @READLINE_LIBS@ @MU_COMMON_LIBRARIES@ 79 @READLINE_LIBS@ @MU_COMMON_LIBRARIES@
71 80
72 INCLUDES = @MU_APP_COMMON_INCLUDES@ @MU_AUTHINCS@ 81 INCLUDES = @MU_APP_COMMON_INCLUDES@ @MU_AUTHINCS@
...@@ -77,7 +86,8 @@ AM_CPPFLAGS = \ ...@@ -77,7 +86,8 @@ AM_CPPFLAGS = \
77 -DAUTHLIBS="\"$(MU_AUTHLIBS)\"" \ 86 -DAUTHLIBS="\"$(MU_AUTHLIBS)\"" \
78 -DGUILE_LIBS="\"$(GUILE_LIBS)\"" \ 87 -DGUILE_LIBS="\"$(GUILE_LIBS)\"" \
79 -DPYTHON_LIBS="\"$(PYTHON_LIBS)\"" \ 88 -DPYTHON_LIBS="\"$(PYTHON_LIBS)\"" \
80 -DI18NLIBS="\"$(LIBINTL)\"" 89 -DI18NLIBS="\"$(LIBINTL)\"" \
90 -DDBMLIBS="\"$(DBMLIBS)\""
81 91
82 BUILT_SOURCES=mu-setup.c mu-setup.h 92 BUILT_SOURCES=mu-setup.c mu-setup.h
83 EXTRA_DIST=mu-setup.awk mu-setup.c mu-setup.h template.c 93 EXTRA_DIST=mu-setup.awk mu-setup.c mu-setup.h template.c
......
1 /* GNU Mailutils -- a suite of utilities for electronic mail
2 Copyright (C) 2010, 2011 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
16
17 #if defined(HAVE_CONFIG_H)
18 # include <config.h>
19 #endif
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <grp.h>
25 #include <sysexits.h>
26 #include <fnmatch.h>
27 #include <regex.h>
28 #include <mailutils/mailutils.h>
29 #include <mailutils/dbm.h>
30 #include "argp.h"
31 #include "mu.h"
32 #include "xalloc.h"
33
34 static char dbm_doc[] = N_("mu dbm - DBM management tool");
35 char dbm_docstring[] = N_("DBM management tool");
36 static char dbm_args_doc[] = N_("FILE [KEY...]");
37
38 enum mode
39 {
40 mode_list,
41 mode_create,
42 mode_delete,
43 mode_add,
44 mode_replace,
45 };
46
47 enum key_type
48 {
49 key_literal,
50 key_glob,
51 key_regex
52 };
53
54 enum mode mode;
55 char *db_name;
56 char *input_file;
57 int permissions = 0600;
58 struct mu_auth_data *auth;
59 uid_t owner_uid = -1;
60 gid_t owner_gid = -1;
61 int copy_permissions;
62 enum key_type key_type = key_literal;
63 int case_sensitive = 1;
64 int include_zero = -1;
65
66 void
67 init_datum (struct mu_dbm_datum *key, char *str)
68 {
69 memset (key, 0, sizeof *key);
70 key->mu_dptr = str;
71 key->mu_dsize = strlen (str) + !!include_zero;
72 }
73
74 mu_dbm_file_t
75 open_db_file (int mode)
76 {
77 int rc;
78 mu_dbm_file_t db;
79
80 rc = mu_dbm_create (db_name, &db);
81 if (rc)
82 {
83 mu_diag_output (MU_DIAG_ERROR, _("unable to create database %s: %s"),
84 db_name, mu_strerror (rc));
85 exit (EX_SOFTWARE);
86 }
87
88 rc = mu_dbm_open (db, mode, permissions);
89 if (rc)
90 {
91 mu_diag_funcall (MU_DIAG_ERROR, "mu_dbm_open", db_name, rc);
92 exit (EX_SOFTWARE);
93 }
94
95 if (mode == MU_STREAM_CREAT && (owner_uid != -1 || owner_gid != -1))
96 {
97 int dirfd, pagfd;
98
99 rc = mu_dbm_get_fd (db, &pagfd, &dirfd);
100 if (rc)
101 {
102 mu_diag_funcall (MU_DIAG_ERROR, "mu_dbm_get_fd", db_name, rc);
103 exit (EX_SOFTWARE);
104 }
105 if (owner_uid == -1 || owner_gid == -1)
106 {
107 struct stat st;
108
109 if (fstat (dirfd, &st))
110 {
111 mu_diag_funcall (MU_DIAG_ERROR, "fstat", db_name, errno);
112 exit (EX_SOFTWARE);
113 }
114 if (owner_uid == -1)
115 owner_uid = st.st_uid;
116 if (owner_gid == -1)
117 owner_gid = st.st_gid;
118 }
119 if (fchown (pagfd, owner_uid, owner_gid))
120 {
121 mu_diag_funcall (MU_DIAG_ERROR, "fchown", db_name, errno);
122 exit (EX_SOFTWARE);
123 }
124 if (pagfd != dirfd &&
125 fchown (dirfd, owner_uid, owner_gid))
126 {
127 mu_diag_funcall (MU_DIAG_ERROR, "fchown", db_name, errno);
128 exit (EX_SOFTWARE);
129 }
130 }
131 return db;
132 }
133
134 struct print_data
135 {
136 mu_dbm_file_t db;
137 mu_stream_t stream;
138 };
139
140 static int
141 print_action (struct mu_dbm_datum const *key, void *data)
142 {
143 int rc;
144 struct mu_dbm_datum contents;
145 struct print_data *pd = data;
146 size_t len;
147
148 memset (&contents, 0, sizeof contents);
149 rc = mu_dbm_fetch (pd->db, key, &contents);
150 if (rc)
151 {
152 mu_error (_("database fetch error: %s"), mu_dbm_strerror (pd->db));
153 exit (EX_UNAVAILABLE);
154 }
155
156 len = key->mu_dsize;
157 if (key->mu_dptr[len - 1] == 0)
158 len--;
159 mu_stream_write (pd->stream, key->mu_dptr, len, NULL);
160 mu_stream_write (pd->stream, "\t", 1, NULL);
161
162 len = contents.mu_dsize;
163 if (contents.mu_dptr[len - 1] == 0)
164 len--;
165 mu_stream_write (pd->stream, contents.mu_dptr, len, NULL);
166 mu_stream_write (pd->stream, "\n", 1, NULL);
167 mu_dbm_datum_free (&contents);
168 return 0;
169 }
170
171 static void
172 iterate_database (mu_dbm_file_t db,
173 int (*matcher) (const char *, void *), void *matcher_data,
174 int (*action) (struct mu_dbm_datum const *, void *),
175 void *action_data)
176 {
177 int rc;
178 struct mu_dbm_datum key;
179 char *buf = NULL;
180 size_t bufsize = 0;
181
182 memset (&key, 0, sizeof key);
183 for (rc = mu_dbm_firstkey (db, &key); rc == 0;
184 rc = mu_dbm_nextkey (db, &key))
185 {
186 if (include_zero == -1)
187 include_zero = key.mu_dptr[key.mu_dsize-1] == 0;
188
189 if (matcher)
190 {
191 if (key.mu_dsize + 1 > bufsize)
192 {
193 bufsize = key.mu_dsize + 1;
194 buf = xrealloc (buf, bufsize);
195 }
196 memcpy (buf, key.mu_dptr, key.mu_dsize);
197 buf[key.mu_dsize] = 0;
198 if (!matcher (buf, matcher_data))
199 continue;
200 }
201 if (action (&key, action_data))
202 break;
203 }
204 free (buf);
205 }
206
207 static int
208 match_literal (const char *str, void *data)
209 {
210 char **argv = data;
211
212 for (; *argv; argv++)
213 {
214 if ((case_sensitive ? strcmp : strcasecmp) (str, *argv) == 0)
215 return 1;
216 }
217 return 0;
218 }
219
220 #ifndef FNM_CASEFOLD
221 # define FNM_CASEFOLD 0
222 #endif
223
224 static int
225 match_glob (const char *str, void *data)
226 {
227 char **argv = data;
228
229 for (; *argv; argv++)
230 {
231 if (fnmatch (*argv, str, case_sensitive ? FNM_CASEFOLD : 0) == 0)
232 return 1;
233 }
234 return 0;
235 }
236
237 struct regmatch
238 {
239 int regc;
240 regex_t *regs;
241 };
242
243 static int
244 match_regex (const char *str, void *data)
245 {
246 struct regmatch *match = data;
247 int i;
248
249 for (i = 0; i < match->regc; i++)
250 {
251 if (regexec (&match->regs[i], str, 0, NULL, 0) == 0)
252 return 1;
253 }
254 return 0;
255 }
256
257 void
258 compile_regexes (int argc, char **argv, struct regmatch *match)
259 {
260 regex_t *regs = xcalloc (argc, sizeof (regs[0]));
261 int i;
262 int cflags = (case_sensitive ? 0: REG_ICASE) | REG_EXTENDED | REG_NOSUB;
263 int errors = 0;
264
265 for (i = 0; i < argc; i++)
266 {
267 int rc = regcomp (&regs[i], argv[i], cflags);
268 if (rc)
269 {
270 char errbuf[512];
271 regerror (rc, &regs[i], errbuf, sizeof (errbuf));
272 mu_error (_("error compiling `%s': %s"), argv[i], errbuf);
273 errors++;
274 }
275 }
276 if (errors)
277 exit (EX_USAGE);
278 match->regc = argc;
279 match->regs = regs;
280 }
281
282 static void
283 free_regexes (struct regmatch *match)
284 {
285 int i;
286 for (i = 0; i < match->regc; i++)
287 regfree (&match->regs[i]);
288 free (match->regs);
289 }
290
291 static void
292 list_database (int argc, char **argv)
293 {
294 mu_dbm_file_t db = open_db_file (MU_STREAM_READ);
295 struct print_data pdata;
296
297 pdata.db = db;
298 pdata.stream = mu_strout;
299
300 if (argc == 0)
301 iterate_database (db, NULL, NULL, print_action, &pdata);
302 else
303 {
304 switch (key_type)
305 {
306 case key_literal:
307 iterate_database (db, match_literal, argv, print_action, &pdata);
308 break;
309
310 case key_glob:
311 iterate_database (db, match_glob, argv, print_action, &pdata);
312 break;
313
314 case key_regex:
315 {
316 struct regmatch m;
317 compile_regexes (argc, argv, &m);
318 iterate_database (db, match_regex, &m, print_action, &pdata);
319 free_regexes (&m);
320 }
321 }
322 }
323 mu_dbm_destroy (&db);
324 }
325
326 void
327 add_records (int mode, int replace)
328 {
329 mu_dbm_file_t db;
330 mu_stream_t input, flt;
331 const char *flt_argv[] = { "inline-comment", "#", "-S", "-i", "#", NULL };
332 char *buf = NULL;
333 size_t size = 0;
334 size_t len;
335 unsigned long line;
336 int rc;
337
338 if (input_file)
339 {
340 rc = mu_file_stream_create (&input, input_file, MU_STREAM_READ);
341 if (rc)
342 {
343 mu_error (_("cannot open input file %s: %s"), input_file,
344 mu_strerror (rc));
345 exit (EX_UNAVAILABLE);
346 }
347 }
348 else
349 input = mu_strin;
350
351 rc = mu_filter_create_args (&flt, input, "inline-comment",
352 MU_ARRAY_SIZE (flt_argv) - 1, flt_argv,
353 MU_FILTER_DECODE, MU_STREAM_READ);
354 if (rc)
355 {
356 mu_diag_funcall (MU_DIAG_ERROR, "mu_filter_create_args", input_file, rc);
357 exit (EX_UNAVAILABLE);
358 }
359 mu_stream_unref (input);
360 input = flt;
361
362 db = open_db_file (mode);
363
364 line = 1;
365 if (!input_file)
366 input_file = "<stdin>";
367 while ((rc = mu_stream_getline (input, &buf, &size, &len)) == 0
368 && len > 0)
369 {
370 struct mu_dbm_datum key, contents;
371 char *kstr, *val;
372
373 mu_rtrim_class (buf, MU_CTYPE_ENDLN);
374 if (buf[0] == '#')
375 {
376 line = strtoul (buf + 1, NULL, 10);
377 continue;
378 }
379 kstr = mu_str_stripws (buf);
380 val = mu_str_skip_class_comp (kstr, MU_CTYPE_SPACE);
381 *val++ = 0;
382 val = mu_str_skip_class (val, MU_CTYPE_SPACE);
383 if (*val == 0)
384 {
385 mu_error (_("%s:%lu: malformed line"), input_file, line);
386 line++;
387 continue;
388 }
389
390 init_datum (&key, kstr);
391 init_datum (&contents, val);
392
393 rc = mu_dbm_store (db, &key, &contents, replace);
394 if (rc)
395 mu_error (_("%s:%lu: cannot store datum: %s"),
396 input_file, line,
397 rc == MU_ERR_FAILURE ?
398 mu_dbm_strerror (db) : mu_strerror (rc));
399 line++;
400 }
401 mu_dbm_destroy (&db);
402
403 mu_stream_unref (input);
404 }
405
406 static void
407 create_database ()
408 {
409 if (copy_permissions)
410 {
411 struct stat st;
412
413 if (!input_file)
414 {
415 mu_error (_("--copy-permissions used without --file"));
416 exit (EX_USAGE);
417 }
418 if (stat (input_file, &st))
419 {
420 mu_diag_funcall (MU_DIAG_ERROR, "stat", input_file, errno);
421 exit (EX_UNAVAILABLE);
422 }
423 owner_uid = st.st_uid;
424 owner_gid = st.st_gid;
425 permissions = st.st_mode & 0777;
426 }
427 else if (auth)
428 {
429 if (owner_uid == -1)
430 owner_uid = auth->uid;
431 if (owner_gid == -1)
432 owner_gid = auth->gid;
433 }
434 add_records (MU_STREAM_CREAT, 0);
435 }
436
437 static int
438 store_to_list (struct mu_dbm_datum const *key, void *data)
439 {
440 int rc;
441 mu_list_t list = data;
442 char *p = xmalloc (key->mu_dsize + 1);
443 memcpy (p, key->mu_dptr, key->mu_dsize);
444 p[key->mu_dsize] = 0;
445 rc = mu_list_append (list, p);
446 if (rc)
447 {
448 mu_diag_funcall (MU_DIAG_ERROR, "mu_list_append", p, rc);
449 exit (EX_SOFTWARE);
450 }
451 return 0;
452 }
453
454 static int
455 do_delete (void *item, void *data)
456 {
457 char *str = item;
458 mu_dbm_file_t db = data;
459 struct mu_dbm_datum key;
460 int rc;
461
462 init_datum (&key, str);
463 rc = mu_dbm_delete (db, &key);
464 if (rc == MU_ERR_NOENT)
465 {
466 mu_error (_("cannot remove record for %s: %s"),
467 str, mu_strerror (rc));
468 }
469 else if (rc)
470 {
471 mu_error (_("cannot remove record for %s: %s"),
472 str, mu_dbm_strerror (db));
473 if (rc != MU_ERR_NOENT)
474 exit (EX_UNAVAILABLE);
475 }
476 return 0;
477 }
478
479 static void
480 delete_database (int argc, char **argv)
481 {
482 mu_dbm_file_t db = open_db_file (MU_STREAM_RDWR);
483 mu_list_t templist = NULL;
484 int rc, i;
485
486 if (argc == 0)
487 {
488 mu_error (_("not enough arguments for delete"));
489 exit (EX_USAGE);
490 }
491
492 /* Collect matching keys */
493 rc = mu_list_create (&templist);
494 if (rc)
495 {
496 mu_diag_funcall (MU_DIAG_ERROR, "mu_list_create", NULL, rc);
497 exit (EX_SOFTWARE);
498 }
499 mu_list_set_destroy_item (templist, mu_list_free_item);
500 switch (key_type)
501 {
502 case key_literal:
503 for (i = 0; i < argc; i++)
504 {
505 char *p = xstrdup (argv[i]);
506 rc = mu_list_append (templist, p);
507 if (rc)
508 {
509 mu_diag_funcall (MU_DIAG_ERROR, "mu_list_append", p, rc);
510 exit (EX_SOFTWARE);
511 }
512 }
513 break;
514
515 case key_glob:
516 iterate_database (db, match_glob, argv,
517 store_to_list, templist);
518 break;
519
520 case key_regex:
521 {
522 struct regmatch m;
523
524 compile_regexes (argc, argv, &m);
525 iterate_database (db, match_regex, &m, store_to_list, templist);
526 free_regexes (&m);
527 }
528 }
529 mu_list_do (templist, do_delete, db);
530 mu_list_destroy (&templist);
531 mu_dbm_destroy (&db);
532 }
533
534 /*
535 mu dbm --create a.db < input
536 mu dbm --list a.db
537 mu dbm --delete a.db key [key...]
538 mu dbm --add a.db < input
539 mu dbm --replace a.db < input
540 */
541
542 static struct argp_option dbm_options[] = {
543 { NULL, 0, NULL, 0, N_("Operation mode"), 0},
544 { "create", 'c', NULL, 0, N_("create the database") },
545 { "list", 'l', NULL, 0, N_("list contents of the database") },
546 { "delete", 'd', NULL, 0, N_("delete specified keys from the database") },
547 { "add", 'a', NULL, 0, N_("add records to the database") },
548 { "replace",'r', NULL, 0, N_("add records replacing ones with matching keys") },
549
550 { NULL, 0, NULL, 0, N_("Create modifiers"), 0},
551 { "file", 'f', N_("FILE"), 0,
552 N_("read input from FILE (with --create, --delete, --add and --replace)") },
553 { "permissions", 'p', N_("NUM"), 0,
554 N_("set permissions on the created database") },
555 { "user", 'u', N_("USER"), 0,
556 N_("set database owner name") },
557 { "group", 'g', N_("GROUP"), 0,
558 N_("set database owner group") },
559 { "copy-permissions", 'P', NULL, 0,
560 N_("copy database permissions and ownership from the input file") },
561 { NULL, 0, NULL, 0, N_("List and Delete modifiers"), 0},
562 { "glob", 'G', NULL, 0,
563 N_("treat keys as globbing patterns") },
564 { "regex", 'R', NULL, 0,
565 N_("treat keys as regular expressions") },
566 { "ignore-case", 'i', NULL, 0,
567 N_("case-insensitive matches") },
568 { NULL, 0, NULL, 0, N_("Data length modifiers"), 0 },
569 { "count-null", 'N', NULL, 0,
570 N_("data length accounts for terminating zero") },
571 { "no-count-null", 'n', NULL, 0,
572 N_("data length does not account for terminating zero") },
573 { NULL }
574 };
575
576 static error_t
577 dbm_parse_opt (int key, char *arg, struct argp_state *state)
578 {
579 switch (key)
580 {
581 case 'c':
582 mode = mode_create;
583 break;
584
585 case 'l':
586 mode = mode_list;
587 break;
588
589 case 'd':
590 mode = mode_delete;
591 break;
592
593 case 'a':
594 mode = mode_add;
595 break;
596
597 case 'r':
598 mode = mode_replace;
599 break;
600
601 case 'f':
602 input_file = arg;
603 break;
604
605 case 'p':
606 {
607 char *p;
608 unsigned long d = strtoul (arg, &p, 8);
609 if (*p || (d & ~0777))
610 argp_error (state, _("invalid file mode: %s"), arg);
611 permissions = d;
612 }
613 break;
614
615 case 'P':
616 copy_permissions = 1;
617 break;
618
619 case 'u':
620 auth = mu_get_auth_by_name (arg);
621 if (!auth)
622 {
623 char *p;
624 unsigned long n = strtoul (arg, &p, 0);
625 if (*p == 0)
626 owner_uid = n;
627 else
628 argp_error (state, _("no such user: %s"), arg);
629 }
630 break;
631
632 case 'g':
633 {
634 struct group *gr = getgrnam (arg);
635 if (!gr)
636 {
637 char *p;
638 unsigned long n = strtoul (arg, &p, 0);
639 if (*p == 0)
640 owner_gid = n;
641 else
642 argp_error (state, _("no such group: %s"), arg);
643 }
644 else
645 owner_gid = gr->gr_gid;
646 }
647 break;
648
649 case 'G':
650 key_type = key_glob;
651 break;
652
653 case 'R':
654 key_type = key_regex;
655 break;
656
657 case 'i':
658 case_sensitive = 0;
659 break;
660
661 case 'N':
662 include_zero = 1;
663 break;
664
665 case 'n':
666 include_zero = 0;
667 break;
668
669 default:
670 return ARGP_ERR_UNKNOWN;
671 }
672 return 0;
673 }
674
675 static struct argp dbm_argp = {
676 dbm_options,
677 dbm_parse_opt,
678 dbm_args_doc,
679 dbm_doc,
680 NULL,
681 NULL,
682 NULL
683 };
684
685 int
686 mutool_dbm (int argc, char **argv)
687 {
688 int index;
689
690 if (argp_parse (&dbm_argp, argc, argv, ARGP_IN_ORDER, &index, NULL))
691 return 1;
692
693 argc -= index;
694 argv += index;
695
696 if (argc == 0)
697 {
698 mu_error (_("database name not given"));
699 exit (EX_USAGE);
700 }
701 db_name = *argv++;
702 --argc;
703
704 switch (mode)
705 {
706 case mode_list:
707 list_database (argc, argv);
708 break;
709
710 case mode_create:
711 if (argc)
712 {
713 mu_error (_("too many arguments for create"));
714 exit (EX_USAGE);
715 }
716 create_database ();
717 break;
718
719 case mode_delete:
720 delete_database (argc, argv);
721 break;
722
723 case mode_add:
724 if (argc)
725 {
726 mu_error (_("too many arguments for add"));
727 exit (EX_USAGE);
728 }
729 add_records (MU_STREAM_RDWR, 0);
730 break;
731
732 case mode_replace:
733 if (argc)
734 {
735 mu_error (_("too many arguments for replace"));
736 exit (EX_USAGE);
737 }
738 add_records (MU_STREAM_RDWR, 1);
739 break;
740 }
741 return 0;
742 }
743
744 /*
745 MU Setup: dbm
746 mu-handler: mutool_dbm
747 mu-docstring: dbm_docstring
748 End MU Setup:
749 */
750
751
...@@ -38,36 +38,52 @@ static struct argp ldflags_argp = { ...@@ -38,36 +38,52 @@ static struct argp ldflags_argp = {
38 38
39 39
40 #ifdef WITH_TLS 40 #ifdef WITH_TLS
41 # define NEEDAUTH 1 41 # define NEEDAUTH "-lmu_auth " AUTHLIBS
42 #else 42 #else
43 # define NEEDAUTH 0 43 # define NEEDAUTH NULL
44 #endif 44 #endif
45 #define NOTALL 2 45 #define NOTALL 1
46 46
47 struct lib_descr { 47 struct lib_descr {
48 char *name; 48 char *name;
49 char *libname; 49 char *libname;
50 int weight;
50 int flags; 51 int flags;
51 } lib_descr[] = { 52 } lib_descr[] = {
52 { "mbox", "mu_mbox", 0 }, 53 { "mbox", "-lmu_mbox", 0 },
53 #ifdef ENABLE_MH 54 #ifdef ENABLE_MH
54 { "mh", "mu_mh", 0 }, 55 { "mh", "-lmu_mh", 0 },
55 #endif 56 #endif
56 #ifdef ENABLE_MAILDIR 57 #ifdef ENABLE_MAILDIR
57 { "maildir","mu_maildir", 0 }, 58 { "maildir", "-lmu_maildir", 0 },
58 #endif 59 #endif
59 #ifdef ENABLE_IMAP 60 #ifdef ENABLE_IMAP
60 { "imap", "mu_imap", NEEDAUTH }, 61 { "imap", "-lmu_imap", 0 },
62 { "imap", NEEDAUTH, 2 },
61 #endif 63 #endif
62 #ifdef ENABLE_POP 64 #ifdef ENABLE_POP
63 { "pop", "mu_pop", NEEDAUTH }, 65 { "pop", "-lmu_pop", 0 },
66 { "pop", NEEDAUTH, 2 },
64 #endif 67 #endif
65 #ifdef ENABLE_NNTP 68 #ifdef ENABLE_NNTP
66 { "nntp", "mu_nntp", 0 }, 69 { "nntp", "-lmu_nntp", 0 },
67 #endif 70 #endif
68 { "mailer", "mu_mailer", 0 }, 71 #ifdef ENABLE_DBM
69 { "sieve", "mu_sieve", NOTALL }, 72 { "dbm", "-lmu_dbm", 0 },
70 { "compat", "mu_compat" }, 73 { "dbm", DBMLIBS, 2 },
74 #endif
75 { "mailer", "-lmu_mailer", 0 },
76 { "sieve", "-lmu_sieve", 0, NOTALL },
77 { "compat", "-lmu_compat", 0 },
78 { "auth", "-lmu_auth " AUTHLIBS, 2 },
79 #ifdef WITH_GUILE
80 { "guile", "-lmu_scm " GUILE_LIBS, -1, NOTALL },
81 #endif
82 #ifdef WITH_PYTHON
83 { "python", "-lmu_py " PYTHON_LIBS, -1, NOTALL },
84 #endif
85 { "cfg", "-lmu_cfg", -1, NOTALL },
86 { "argp", "-lmu_argp", -2, NOTALL },
71 { NULL } 87 { NULL }
72 }; 88 };
73 89
...@@ -82,6 +98,9 @@ void ...@@ -82,6 +98,9 @@ void
82 add_entry (int level, char *ptr) 98 add_entry (int level, char *ptr)
83 { 99 {
84 int i; 100 int i;
101
102 if (!ptr || !*ptr)
103 return;
85 if (nentry >= sizeof(lib_entry)/sizeof(lib_entry[0])) 104 if (nentry >= sizeof(lib_entry)/sizeof(lib_entry[0]))
86 { 105 {
87 mu_error (_("too many arguments")); 106 mu_error (_("too many arguments"));
...@@ -122,7 +141,6 @@ int ...@@ -122,7 +141,6 @@ int
122 mutool_ldflags (int argc, char **argv) 141 mutool_ldflags (int argc, char **argv)
123 { 142 {
124 int i, j; 143 int i, j;
125 char *ptr;
126 144
127 if (argp_parse (&ldflags_argp, argc, argv, ARGP_IN_ORDER, &i, NULL)) 145 if (argp_parse (&ldflags_argp, argc, argv, ARGP_IN_ORDER, &i, NULL))
128 return 1; 146 return 1;
...@@ -140,21 +158,7 @@ mutool_ldflags (int argc, char **argv) ...@@ -140,21 +158,7 @@ mutool_ldflags (int argc, char **argv)
140 158
141 for ( ; argc > 0; argc--, argv++) 159 for ( ; argc > 0; argc--, argv++)
142 { 160 {
143 if (strcmp (argv[0], "auth") == 0) 161 if (strcmp (argv[0], "all") == 0)
144 add_entry (2, "-lmu_auth " AUTHLIBS);
145 #ifdef WITH_GUILE
146 else if (strcmp (argv[0], "guile") == 0)
147 add_entry (-1, "-lmu_scm " GUILE_LIBS);
148 #endif
149 #ifdef WITH_PYTHON
150 else if (strcmp (argv[0], "python") == 0)
151 add_entry (-1, "-lmu_py " PYTHON_LIBS);
152 #endif
153 else if (strcmp (argv[0], "cfg") == 0)
154 add_entry (-1, "-lmu_cfg");
155 else if (strcmp (argv[0], "argp") == 0)
156 add_entry (-2, "-lmu_argp");
157 else if (strcmp (argv[0], "all") == 0)
158 { 162 {
159 struct lib_descr *p; 163 struct lib_descr *p;
160 164
...@@ -162,28 +166,24 @@ mutool_ldflags (int argc, char **argv) ...@@ -162,28 +166,24 @@ mutool_ldflags (int argc, char **argv)
162 { 166 {
163 if (p->flags & NOTALL) 167 if (p->flags & NOTALL)
164 continue; 168 continue;
165 mu_asprintf (&ptr, "-l%s", p->libname); 169 add_entry (p->weight, p->libname);
166 add_entry (0, ptr);
167 if (p->flags & NEEDAUTH)
168 add_entry (2, "-lmu_auth " AUTHLIBS);
169 } 170 }
170 } 171 }
171 else 172 else
172 { 173 {
173 struct lib_descr *p; 174 struct lib_descr *p;
175 int found = 0;
174 176
175 for (p = lib_descr; p->name; p++) 177 for (p = lib_descr; p->name; p++)
176 if (mu_c_strcasecmp (p->name, argv[0]) == 0)
177 break;
178
179 if (p->name)
180 { 178 {
181 mu_asprintf (&ptr, "-l%s", p->libname); 179 if (mu_c_strcasecmp (p->name, argv[0]) == 0)
182 add_entry (0, ptr); 180 {
183 if (p->flags & NEEDAUTH) 181 add_entry (p->weight, p->libname);
184 add_entry (2, "-lmu_auth " AUTHLIBS); 182 found = 1;
183 }
185 } 184 }
186 else 185
186 if (!found)
187 { 187 {
188 mu_error (_("unknown keyword: %s"), argv[0]); 188 mu_error (_("unknown keyword: %s"), argv[0]);
189 return 1; 189 return 1;
......
...@@ -46,6 +46,10 @@ pop3d_SOURCES =\ ...@@ -46,6 +46,10 @@ pop3d_SOURCES =\
46 uidl.c\ 46 uidl.c\
47 user.c 47 user.c
48 48
49 if MU_COND_DBM
50 LIBMU_DBM=../libmu_dbm/libmu_dbm.la
51 endif
52
49 pop3d_LDADD = \ 53 pop3d_LDADD = \
50 ${MU_APP_LIBRARIES}\ 54 ${MU_APP_LIBRARIES}\
51 ${MU_LIB_MBOX}\ 55 ${MU_LIB_MBOX}\
...@@ -54,15 +58,25 @@ pop3d_LDADD = \ ...@@ -54,15 +58,25 @@ pop3d_LDADD = \
54 ${MU_LIB_AUTH}\ 58 ${MU_LIB_AUTH}\
55 @MU_AUTHLIBS@ \ 59 @MU_AUTHLIBS@ \
56 ${MU_LIB_MAILUTILS}\ 60 ${MU_LIB_MAILUTILS}\
57 @MU_COMMON_LIBRARIES@ @TCPWRAP_LIBRARIES@ 61 @MU_COMMON_LIBRARIES@\
62 ${LIBMU_DBM}\
63 @DBMLIBS@\
64 @TCPWRAP_LIBRARIES@
58 65
59 popauth_SOURCES = popauth.c 66 popauth_SOURCES = popauth.c
60 popauth_LDADD = ${MU_APP_LIBRARIES} ${MU_LIB_MAILUTILS} @MU_COMMON_LIBRARIES@ 67 popauth_LDADD = \
68 ${MU_APP_LIBRARIES}\
69 ${MU_LIB_MAILUTILS}\
70 @MU_COMMON_LIBRARIES@\
71 ${LIBMU_DBM}\
72 @DBMLIBS@
73
61 pop3d_DEPENDENCIES = \ 74 pop3d_DEPENDENCIES = \
62 @MU_AUTHLIBS_DEPENDENCY@ \ 75 @MU_AUTHLIBS_DEPENDENCY@ \
63 ../lib/libmuaux.a \ 76 ../lib/libmuaux.a \
64 ${MU_LIB_MBOX}\ 77 ${MU_LIB_MBOX}\
65 ${MU_LIB_MH}\ 78 ${MU_LIB_MH}\
66 ${MU_LIB_MAILDIR}\ 79 ${MU_LIB_MAILDIR}\
67 ${MU_LIB_MAILUTILS} 80 ${MU_LIB_MAILUTILS}\
81 ${LIBMU_DBM}
68 82
......
...@@ -43,59 +43,85 @@ pop3d_apopuser (const char *user) ...@@ -43,59 +43,85 @@ pop3d_apopuser (const char *user)
43 { 43 {
44 char *password = NULL; 44 char *password = NULL;
45 45
46 #ifdef USE_DBM 46 #ifdef ENABLE_DBM
47 { 47 {
48 size_t len; 48 size_t len;
49 DBM_FILE db; 49 mu_dbm_file_t db;
50 DBM_DATUM key, data; 50 struct mu_dbm_datum key, data;
51 int rc;
51 52
52 int rc = mu_dbm_open (APOP_PASSFILE, &db, MU_STREAM_READ, 0600); 53 rc = mu_dbm_create (APOP_PASSFILE, &db);
54 if (rc)
55 {
56 mu_diag_output (MU_DIAG_ERROR, _("unable to create APOP db"));
57 return NULL;
58 }
59
60 rc = mu_dbm_safety_check (db);
61 if (rc)
62 {
63 mu_diag_output (MU_DIAG_ERROR,
64 _("APOP file %s fails safety check: %s"),
65 APOP_PASSFILE, mu_strerror (rc));
66 mu_dbm_destroy (&db);
67 return NULL;
68 }
69
70 rc = mu_dbm_open (db, MU_STREAM_READ, 0600);
53 if (rc) 71 if (rc)
54 { 72 {
55 mu_diag_output (MU_DIAG_ERROR, _("unable to open APOP db: %s"), 73 mu_diag_output (MU_DIAG_ERROR, _("unable to open APOP db: %s"),
56 mu_strerror (errno)); 74 mu_strerror (rc));
57 return NULL; 75 return NULL;
58 } 76 }
59 77
60 memset (&key, 0, sizeof key); 78 memset (&key, 0, sizeof key);
61 memset (&data, 0, sizeof data); 79 memset (&data, 0, sizeof data);
62 80
63 MU_DATUM_PTR (key) = (void*) user; 81 key.mu_dptr = (void *)user;
64 MU_DATUM_SIZE (key) = strlen (user); 82 key.mu_dsize = strlen (user);
65 83
66 rc = mu_dbm_fetch (db, key, &data); 84 rc = mu_dbm_fetch (db, &key, &data);
67 mu_dbm_close (db); 85 if (rc == MU_ERR_NOENT)
68 if (rc) 86 {
87 mu_dbm_destroy (&db);
88 return NULL;
89 }
90 else if (rc)
69 { 91 {
70 mu_diag_output (MU_DIAG_ERROR, 92 mu_diag_output (MU_DIAG_ERROR,
71 _("cannot fetch APOP data: %s"), mu_strerror (errno)); 93 _("cannot fetch APOP data: %s"),
94 mu_dbm_strerror (db));
95 mu_dbm_destroy (&db);
72 return NULL; 96 return NULL;
73 } 97 }
74 len = MU_DATUM_SIZE (data); 98 mu_dbm_destroy (&db);
99 len = data.mu_dsize;
75 password = malloc (len + 1); 100 password = malloc (len + 1);
76 if (password == NULL) 101 if (password == NULL)
77 { 102 {
78 mu_dbm_datum_free (&data); 103 mu_dbm_datum_free (&data);
79 return NULL; 104 return NULL;
80 } 105 }
81 memcpy (password, MU_DATUM_PTR (data), len); 106 memcpy (password, data.mu_dptr, len);
82 password[len] = 0; 107 password[len] = 0;
83 mu_dbm_datum_free (&data); 108 mu_dbm_datum_free (&data);
84 return password; 109 return password;
85 } 110 }
86 #else /* !USE_DBM */ 111 #else /* !ENABLE_DBM */
87 { 112 {
88 char *buf = NULL; 113 char *buf = NULL;
89 size_t size = 0; 114 size_t size = 0;
90 size_t ulen; 115 size_t ulen;
91 FILE *apop_file; 116 FILE *apop_file;
92 117
93 if (mu_check_perm (APOP_PASSFILE, 0600)) 118 /* FIXME */
94 { 119 /* if (mu_check_perm (APOP_PASSFILE, 0600)) */
95 mu_diag_output (MU_DIAG_INFO, 120 /* { */
96 _("bad permissions on APOP password file")); 121 /* mu_diag_output (MU_DIAG_INFO, */
97 return NULL; 122 /* _("bad permissions on APOP password file")); */
98 } 123 /* return NULL; */
124 /* } */
99 125
100 apop_file = fopen (APOP_PASSFILE, "r"); 126 apop_file = fopen (APOP_PASSFILE, "r");
101 if (apop_file == NULL) 127 if (apop_file == NULL)
......
...@@ -113,58 +113,72 @@ write_popbull_file (size_t num) ...@@ -113,58 +113,72 @@ write_popbull_file (size_t num)
113 return rc; 113 return rc;
114 } 114 }
115 115
116 #ifdef USE_DBM 116 #ifdef ENABLE_DBM
117 int 117 int
118 read_bulletin_db (size_t *pnum) 118 read_bulletin_db (size_t *pnum)
119 { 119 {
120 DBM_FILE db; 120 mu_dbm_file_t db;
121 DBM_DATUM key, data; 121 struct mu_dbm_datum key, data;
122 int rc; 122 int rc;
123 char sbuf[128]; 123 char sbuf[128];
124 char *bufptr; 124 char *bufptr;
125 char *buf = NULL; 125 char *buf = NULL;
126 size_t s; 126 size_t s;
127 char *p; 127 char *p;
128 128
129 rc = mu_dbm_open (bulletin_db_name, &db, MU_STREAM_READ, 0660); 129 rc = mu_dbm_create (bulletin_db_name, &db);
130 if (rc) 130 if (rc)
131 { 131 {
132 if (errno == ENOENT) 132 mu_diag_output (MU_DIAG_ERROR, _("unable to create bulletin db"));
133 return rc;
134 }
135
136 rc = mu_dbm_safety_check (db);
137 if (rc)
138 {
139 if (rc == ENOENT)
133 { 140 {
134 *pnum = 0; 141 *pnum = 0;
135 return 0; 142 return 0;
136 } 143 }
137 else 144 mu_diag_output (MU_DIAG_ERROR,
138 { 145 _("bulletin db %s fails safety check: %s"),
139 mu_error (_("unable to open bulletin db for reading: %s"), 146 bulletin_db_name, mu_strerror (rc));
140 mu_strerror (errno)); 147 mu_dbm_destroy (&db);
141 return rc; 148 return 1;
142 } 149 }
150
151 rc = mu_dbm_open (db, MU_STREAM_READ, 0660);
152 if (rc)
153 {
154 mu_error (_("unable to open bulletin db for reading: %s"),
155 mu_strerror (rc));
156 return rc;
143 } 157 }
144 158
145 memset (&key, 0, sizeof key); 159 memset (&key, 0, sizeof key);
146 memset (&data, 0, sizeof data); 160 memset (&data, 0, sizeof data);
147 161
148 MU_DATUM_PTR(key) = username; 162 key.mu_dptr = username;
149 MU_DATUM_SIZE(key) = strlen (username); 163 key.mu_dsize = strlen (username);
150 164
151 rc = mu_dbm_fetch (db, key, &data); 165 rc = mu_dbm_fetch (db, &key, &data);
152 166
153 if (rc) 167 if (rc == MU_ERR_NOENT)
168 {
169 *pnum = 0;
170 return 0;
171 }
172 else if (rc)
154 { 173 {
155 int ec = errno;
156 if (ec == ENOENT)
157 {
158 *pnum = 0;
159 return 0;
160 }
161 mu_error (_("cannot fetch bulletin db data: %s"), 174 mu_error (_("cannot fetch bulletin db data: %s"),
162 mu_strerror (ec)); 175 mu_dbm_strerror (db));
163 mu_dbm_close (db); 176 mu_dbm_destroy (&db);
164 return 1; 177 return 1;
165 } 178 }
179 mu_dbm_destroy (&db);
166 180
167 s = MU_DATUM_SIZE (data); 181 s = data.mu_dsize;
168 if (s < sizeof sbuf) 182 if (s < sizeof sbuf)
169 bufptr = sbuf; 183 bufptr = sbuf;
170 else 184 else
...@@ -172,16 +186,15 @@ read_bulletin_db (size_t *pnum) ...@@ -172,16 +186,15 @@ read_bulletin_db (size_t *pnum)
172 buf = malloc (s + 1); 186 buf = malloc (s + 1);
173 if (!buf) 187 if (!buf)
174 { 188 {
175 mu_error("%s", mu_strerror (errno)); 189 mu_error ("%s", mu_strerror (errno));
176 return 1; 190 return 1;
177 } 191 }
178 bufptr = buf; 192 bufptr = buf;
179 } 193 }
180 194
181 memcpy (bufptr, MU_DATUM_PTR (data), s); 195 memcpy (bufptr, data.mu_dptr, s);
182 bufptr[s] = 0; 196 bufptr[s] = 0;
183 mu_dbm_datum_free(&data); 197 mu_dbm_datum_free (&data);
184 mu_dbm_close (db);
185 198
186 rc = 1; 199 rc = 1;
187 *pnum = strtoul (bufptr, &p, 0); 200 *pnum = strtoul (bufptr, &p, 0);
...@@ -189,26 +202,8 @@ read_bulletin_db (size_t *pnum) ...@@ -189,26 +202,8 @@ read_bulletin_db (size_t *pnum)
189 rc = 0; 202 rc = 0;
190 else 203 else
191 { 204 {
192 #ifdef QPOPPER_COMPAT 205 mu_error (_("wrong bulletin database format for `%s'"),
193 if (s == sizeof long) 206 username);
194 {
195 long n;
196
197 n = *(long*)MU_DATUM_PTR (data);
198 if (n >= 0)
199 {
200 mu_diag_output (MU_DIAG_INFO,
201 _("assuming bulletin database is in qpopper format"));
202 *pnum = n;
203 rc = 0;
204 }
205 }
206 else
207 #endif /* QPOPPER_COMPAT */
208 {
209 mu_error (_("wrong bulletin database format for `%s'"),
210 username);
211 }
212 } 207 }
213 208
214 free (buf); 209 free (buf);
...@@ -218,41 +213,60 @@ read_bulletin_db (size_t *pnum) ...@@ -218,41 +213,60 @@ read_bulletin_db (size_t *pnum)
218 int 213 int
219 write_bulletin_db (size_t num) 214 write_bulletin_db (size_t num)
220 { 215 {
221 DBM_FILE db; 216 mu_dbm_file_t db;
222 DBM_DATUM key, data; 217 struct mu_dbm_datum key, data;
223 int rc; 218 int rc;
224 const char *p; 219 const char *p;
225 220
226 rc = mu_dbm_open (bulletin_db_name, &db, MU_STREAM_RDWR, 0660); 221 rc = mu_dbm_create (bulletin_db_name, &db);
222 if (rc)
223 {
224 mu_diag_output (MU_DIAG_ERROR, _("unable to create bulletin db"));
225 return rc;
226 }
227
228 rc = mu_dbm_safety_check (db);
229 if (rc && rc != ENOENT)
230 {
231 mu_diag_output (MU_DIAG_ERROR,
232 _("bulletin db %s fails safety check: %s"),
233 bulletin_db_name, mu_strerror (rc));
234 mu_dbm_destroy (&db);
235 return rc;
236 }
237
238 rc = mu_dbm_open (db, MU_STREAM_RDWR, 0660);
227 if (rc) 239 if (rc)
228 { 240 {
229 mu_error (_("unable to open bulletin db for writing: %s"), 241 mu_error (_("unable to open bulletin db for writing: %s"),
230 mu_strerror (errno)); 242 mu_strerror (rc));
243 mu_dbm_destroy (&db);
231 return rc; 244 return rc;
232 } 245 }
233 246
234 memset (&key, 0, sizeof key); 247 memset (&key, 0, sizeof key);
235 memset (&data, 0, sizeof data); 248 memset (&data, 0, sizeof data);
236 249
237 MU_DATUM_PTR (key) = username; 250 key.mu_dptr = username;
238 MU_DATUM_SIZE (key) = strlen (username); 251 key.mu_dsize = strlen (username);
239 p = mu_umaxtostr (0, num); 252 p = mu_umaxtostr (0, num);
240 MU_DATUM_PTR (data) = (char *) p; 253 data.mu_dptr = (char *) p;
241 MU_DATUM_SIZE (data) = strlen (p); 254 data.mu_dsize = strlen (p);
242 255
243 rc = mu_dbm_insert (db, key, data, 1); 256 rc = mu_dbm_store (db, &key, &data, 1);
244 if (rc) 257 if (rc)
245 mu_error (_("cannot store datum in bulletin db")); 258 mu_error (_("cannot store datum in bulletin db: %s"),
246 259 mu_dbm_strerror (db));
247 mu_dbm_close (db); 260
261 mu_dbm_destroy (&db);
248 return rc; 262 return rc;
249 } 263 }
250 #endif /* USE_DBM */ 264 #endif /* ENABLE_DBM */
251 265
252 int 266 int
253 get_last_delivered_num (size_t *pret) 267 get_last_delivered_num (size_t *pret)
254 { 268 {
255 #ifdef USE_DBM 269 #ifdef ENABLE_DBM
256 if (bulletin_db_name && read_bulletin_db (pret) == 0) 270 if (bulletin_db_name && read_bulletin_db (pret) == 0)
257 return 0; 271 return 0;
258 #endif 272 #endif
...@@ -262,7 +276,7 @@ get_last_delivered_num (size_t *pret) ...@@ -262,7 +276,7 @@ get_last_delivered_num (size_t *pret)
262 void 276 void
263 store_last_delivered_num (size_t num) 277 store_last_delivered_num (size_t num)
264 { 278 {
265 #ifdef USE_DBM 279 #ifdef ENABLE_DBM
266 if (bulletin_db_name && write_bulletin_db (num) == 0) 280 if (bulletin_db_name && write_bulletin_db (num) == 0)
267 return; 281 return;
268 #endif 282 #endif
......
...@@ -19,27 +19,45 @@ ...@@ -19,27 +19,45 @@
19 19
20 #ifdef ENABLE_LOGIN_DELAY 20 #ifdef ENABLE_LOGIN_DELAY
21 21
22 static int 22 static mu_dbm_file_t
23 open_stat_db (DBM_FILE *db, int mode) 23 open_stat_db (int mode)
24 { 24 {
25 int rc = mu_dbm_open (login_stat_file, db, mode, 0660); 25 mu_dbm_file_t db;
26 int rc;
27
28 rc = mu_dbm_create (login_stat_file, &db);
26 if (rc) 29 if (rc)
27 { 30 {
28 if (rc == -1) 31 mu_diag_output (MU_DIAG_ERROR, _("unable to create statistics db"));
29 mu_diag_output (MU_DIAG_INFO, _("bad permissions on statistics db")); 32 return NULL;
30 else 33 }
31 mu_diag_output (MU_DIAG_ERROR, _("unable to open statistics db: %s"), 34
32 mu_strerror (rc)); 35 rc = mu_dbm_safety_check (db);
36 if (rc)
37 {
38 mu_diag_output (MU_DIAG_ERROR,
39 _("statistics db fails safety check: %s"),
40 mu_strerror (rc));
41 mu_dbm_destroy (&db);
42 return NULL;
33 } 43 }
34 return rc; 44
45 rc = mu_dbm_open (db, mode, 0660);
46 if (rc)
47 {
48 mu_diag_output (MU_DIAG_ERROR, _("unable to open statistics db: %s"),
49 mu_dbm_strerror (db));
50 mu_dbm_destroy (&db);
51 }
52 return db;
35 } 53 }
36 54
37 int 55 int
38 check_login_delay (char *username) 56 check_login_delay (char *username)
39 { 57 {
40 time_t now, prev_time; 58 time_t now, prev_time;
41 DBM_FILE db; 59 mu_dbm_file_t db;
42 DBM_DATUM key, data; 60 struct mu_dbm_datum key, data;
43 char text[64], *p; 61 char text[64], *p;
44 int rc; 62 int rc;
45 63
...@@ -47,42 +65,45 @@ check_login_delay (char *username) ...@@ -47,42 +65,45 @@ check_login_delay (char *username)
47 return 0; 65 return 0;
48 66
49 time (&now); 67 time (&now);
50 if (open_stat_db (&db, MU_STREAM_RDWR)) 68 db = open_stat_db (MU_STREAM_READ);
69 if (!db)
51 return 0; 70 return 0;
52 71
53 memset (&key, 0, sizeof key); 72 memset (&key, 0, sizeof key);
54 MU_DATUM_PTR(key) = username; 73 key.mu_dptr = username;
55 MU_DATUM_SIZE(key) = strlen (username); 74 key.mu_dsize = strlen (username);
56 memset (&data, 0, sizeof data); 75 memset (&data, 0, sizeof data);
57 76
58 rc = mu_dbm_fetch (db, key, &data); 77 rc = mu_dbm_fetch (db, &key, &data);
59 if (rc) 78 if (rc)
60 { 79 {
61 mu_diag_output (MU_DIAG_ERROR, _("cannot fetch login delay data: %s"), 80 if (rc != MU_ERR_NOENT)
62 mu_strerror (rc)); 81 mu_diag_output (MU_DIAG_ERROR, _("cannot fetch login delay data: %s"),
63 mu_dbm_close (db); 82 mu_dbm_strerror (db));
83 mu_dbm_destroy (&db);
64 return 0; 84 return 0;
65 } 85 }
66 86
67 if (MU_DATUM_SIZE(data) > sizeof (text) - 1) 87 if (data.mu_dsize > sizeof (text) - 1)
68 { 88 {
69 mu_diag_output (MU_DIAG_ERROR, 89 mu_diag_output (MU_DIAG_ERROR,
70 _("invalid entry for '%s': wrong timestamp size"), 90 _("invalid entry for '%s': wrong timestamp size"),
71 username); 91 username);
72 mu_dbm_close (db); 92 mu_dbm_destroy (&db);
73 return 0; 93 return 0;
74 } 94 }
95 mu_dbm_destroy (&db);
75 96
76 memcpy (text, MU_DATUM_PTR(data), MU_DATUM_SIZE(data)); 97 memcpy (text, data.mu_dptr, data.mu_dsize);
77 text[MU_DATUM_SIZE(data)] = 0; 98 text[data.mu_dsize] = 0;
78 mu_dbm_close (db); 99 mu_dbm_datum_free (&data);
79 100
80 prev_time = strtoul (text, &p, 0); 101 prev_time = strtoul (text, &p, 0);
81 if (*p) 102 if (*p)
82 { 103 {
83 mu_diag_output (MU_DIAG_ERROR, 104 mu_diag_output (MU_DIAG_ERROR,
84 _("malformed timestamp for '%s': %s"), 105 _("malformed timestamp for '%s': %s"),
85 username, text); 106 username, text);
86 return 0; 107 return 0;
87 } 108 }
88 109
...@@ -93,40 +114,42 @@ void ...@@ -93,40 +114,42 @@ void
93 update_login_delay (char *username) 114 update_login_delay (char *username)
94 { 115 {
95 time_t now; 116 time_t now;
96 DBM_FILE db; 117 mu_dbm_file_t db;
97 DBM_DATUM key, data; 118 struct mu_dbm_datum key, data;
98 char text[64]; 119 char text[64];
99 120
100 if (login_delay == 0 || username == NULL) 121 if (login_delay == 0 || username == NULL)
101 return; 122 return;
102 123
103 time (&now); 124 time (&now);
104 if (open_stat_db (&db, MU_STREAM_RDWR)) 125 db = open_stat_db (MU_STREAM_RDWR);
126 if (!db)
105 return; 127 return;
106 128
107 memset(&key, 0, sizeof(key)); 129 memset(&key, 0, sizeof(key));
108 memset(&data, 0, sizeof(data)); 130 memset(&data, 0, sizeof(data));
109 MU_DATUM_PTR(key) = username; 131 key.mu_dptr = username;
110 MU_DATUM_SIZE(key) = strlen (username); 132 key.mu_dsize = strlen (username);
111 snprintf (text, sizeof text, "%lu", (unsigned long) now); 133 snprintf (text, sizeof text, "%lu", (unsigned long) now);
112 MU_DATUM_PTR(data) = text; 134 data.mu_dptr = text;
113 MU_DATUM_SIZE(data) = strlen (text); 135 data.mu_dsize = strlen (text);
114 if (mu_dbm_insert (db, key, data, 1)) 136 if (mu_dbm_store (db, &key, &data, 1))
115 mu_error (_("%s: cannot store datum %s/%s"), 137 mu_error (_("%s: cannot store datum %s/%s: %s"),
116 login_stat_file, username, text); 138 login_stat_file, username, text,
139 mu_dbm_strerror (db));
117 140
118 mu_dbm_close (db); 141 mu_dbm_destroy (&db);
119 } 142 }
120 143
121 void 144 void
122 login_delay_capa () 145 login_delay_capa ()
123 { 146 {
124 DBM_FILE db; 147 mu_dbm_file_t db;
125 148
126 if (login_delay && open_stat_db (&db, MU_STREAM_RDWR) == 0) 149 if (login_delay && (db = open_stat_db (MU_STREAM_RDWR)) != NULL)
127 { 150 {
128 pop3d_outf ("LOGIN-DELAY %s\n", mu_umaxtostr (0, login_delay)); 151 pop3d_outf ("LOGIN-DELAY %s\n", mu_umaxtostr (0, login_delay));
129 mu_dbm_close (db); 152 mu_dbm_destroy (&db);
130 } 153 }
131 } 154 }
132 #endif 155 #endif
......
...@@ -77,7 +77,7 @@ cb_bulletin_source (void *data, mu_config_value_t *val) ...@@ -77,7 +77,7 @@ cb_bulletin_source (void *data, mu_config_value_t *val)
77 return 0; 77 return 0;
78 } 78 }
79 79
80 #ifdef USE_DBM 80 #ifdef ENABLE_DBM
81 static int 81 static int
82 cb_bulletin_db (void *data, mu_config_value_t *val) 82 cb_bulletin_db (void *data, mu_config_value_t *val)
83 { 83 {
...@@ -111,7 +111,7 @@ static struct mu_cfg_param pop3d_cfg_param[] = { ...@@ -111,7 +111,7 @@ static struct mu_cfg_param pop3d_cfg_param[] = {
111 { "bulletin-source", mu_cfg_callback, NULL, 0, cb_bulletin_source, 111 { "bulletin-source", mu_cfg_callback, NULL, 0, cb_bulletin_source,
112 N_("Get bulletins from the specified mailbox."), 112 N_("Get bulletins from the specified mailbox."),
113 N_("url") }, 113 N_("url") },
114 #ifdef USE_DBM 114 #ifdef ENABLE_DBM
115 { "bulletin-db", mu_cfg_callback, NULL, 0, cb_bulletin_db, 115 { "bulletin-db", mu_cfg_callback, NULL, 0, cb_bulletin_db,
116 N_("Set the bulletin database file name."), 116 N_("Set the bulletin database file name."),
117 N_("file") }, 117 N_("file") },
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
24 #include <mailutils/types.h> 24 #include <mailutils/types.h>
25 #include <mailutils/stream.h> 25 #include <mailutils/stream.h>
26 #include <mailutils/io.h> 26 #include <mailutils/io.h>
27 #include <mu_dbm.h> 27 #include <mailutils/dbm.h>
28 #include <mu_umaxtostr.h> 28 #include <mu_umaxtostr.h>
29 #include <muaux.h> 29 #include <muaux.h>
30 30
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
35 type automatically */ 35 type automatically */
36 #define APOP_PASSFILE_NAME "apop" 36 #define APOP_PASSFILE_NAME "apop"
37 37
38 #ifdef USE_DBM 38 #ifdef ENABLE_DBM
39 # define APOP_PASSFILE SYSCONFDIR "/" APOP_PASSFILE_NAME 39 # define APOP_PASSFILE SYSCONFDIR "/" APOP_PASSFILE_NAME
40 # define ENABLE_LOGIN_DELAY 40 # define ENABLE_LOGIN_DELAY
41 #else 41 #else
......
...@@ -73,7 +73,7 @@ static struct argp_option options[] = ...@@ -73,7 +73,7 @@ static struct argp_option options[] =
73 73
74 { NULL, 0, NULL, 0, 74 { NULL, 0, NULL, 0,
75 N_("Default action is:\n" 75 N_("Default action is:\n"
76 " For the file owner: --list\n" 76 " For root: --list\n"
77 " For a user: --modify --user <username>\n"), 2 }, 77 " For a user: --modify --user <username>\n"), 2 },
78 78
79 { NULL, 0, NULL, 0, N_("Options are:"), 3 }, 79 { NULL, 0, NULL, 0, N_("Options are:"), 3 },
...@@ -197,7 +197,7 @@ popauth_parse_opt (int key, char *arg, struct argp_state *astate) ...@@ -197,7 +197,7 @@ popauth_parse_opt (int key, char *arg, struct argp_state *astate)
197 } 197 }
198 198
199 int 199 int
200 main(int argc, char **argv) 200 main (int argc, char **argv)
201 { 201 {
202 struct action_data adata; 202 struct action_data adata;
203 203
...@@ -223,41 +223,121 @@ check_action (int action) ...@@ -223,41 +223,121 @@ check_action (int action)
223 } 223 }
224 } 224 }
225 225
226 int 226 mu_dbm_file_t
227 check_user_perm (int action, struct action_data *ap) 227 open_db_file (int action, struct action_data *ap, int *my_file)
228 { 228 {
229 struct stat sb; 229 mu_dbm_file_t db;
230 struct passwd *pw; 230 struct passwd *pw;
231 uid_t uid; 231 uid_t uid;
232 int rc;
233 int flags = 0;
234 char *db_name = NULL;
235 int fd;
236 struct stat sb;
237 int safety_flags = MU_FILE_SAFETY_ALL & ~MU_FILE_SAFETY_OWNER_MISMATCH;
232 238
233 if (!ap->input_name) 239 switch (action)
234 ap->input_name = APOP_PASSFILE;
235
236 if (mu_dbm_stat (ap->input_name, &sb))
237 { 240 {
238 if (ap->action == ACT_ADD) 241 case ACT_CREATE:
239 { 242 flags = MU_STREAM_CREAT;
240 DBM_FILE db; 243 safety_flags = MU_FILE_SAFETY_NONE;
241 if (mu_dbm_open (ap->input_name, &db, MU_STREAM_CREAT, permissions)) 244 db_name = ap->output_name;
242 { 245 break;
243 mu_diag_funcall (MU_DIAG_ERROR, "mu_dbm_open", 246
244 ap->input_name, errno); 247 case ACT_ADD:
245 exit (EX_SOFTWARE); 248 case ACT_DELETE:
246 } 249 if (!ap->input_name)
247 mu_dbm_close (db); 250 ap->input_name = APOP_PASSFILE;
248 mu_dbm_stat (ap->input_name, &sb); 251 flags = MU_STREAM_RDWR;
249 } 252 db_name = ap->input_name;
250 else 253 break;
251 { 254
252 mu_diag_funcall (MU_DIAG_ERROR, "stat", ap->input_name, errno); 255 case ACT_LIST:
253 exit (EX_OSERR); 256 if (!ap->input_name)
254 } 257 ap->input_name = APOP_PASSFILE;
258 flags = MU_STREAM_READ;
259 safety_flags = MU_FILE_SAFETY_NONE;
260 db_name = ap->input_name;
261 break;
262
263 case ACT_CHPASS:
264 if (!ap->input_name)
265 ap->input_name = APOP_PASSFILE;
266 flags = MU_STREAM_RDWR;
267 db_name = ap->input_name;
268 break;
269
270 default:
271 abort ();
255 } 272 }
256 273
257 uid = getuid (); 274 uid = getuid ();
258 if (uid == 0 || sb.st_uid == uid)
259 return 0;
260 275
276 rc = mu_dbm_create (db_name, &db);
277 if (rc)
278 {
279 mu_diag_output (MU_DIAG_ERROR, _("unable to create database %s: %s"),
280 db_name, mu_strerror (rc));
281 exit (EX_SOFTWARE);
282 }
283
284 // mu_dbm_safety_set_owner (db, uid);
285 /* Adjust safety flags */
286 if (permissions & 0002)
287 safety_flags &= ~MU_FILE_SAFETY_WORLD_WRITABLE;
288 if (permissions & 0004)
289 safety_flags &= ~MU_FILE_SAFETY_WORLD_READABLE;
290 if (permissions & 0020)
291 safety_flags &= ~MU_FILE_SAFETY_GROUP_WRITABLE;
292 if (permissions & 0040)
293 safety_flags &= ~MU_FILE_SAFETY_GROUP_READABLE;
294
295 mu_dbm_safety_set_flags (db, safety_flags);
296 rc = mu_dbm_safety_check (db);
297 if (rc && rc != ENOENT)
298 {
299 mu_diag_output (MU_DIAG_ERROR,
300 _("%s fails safety check: %s"),
301 db_name, mu_strerror (rc));
302 mu_dbm_destroy (&db);
303 exit (EX_UNAVAILABLE);
304 }
305
306 rc = mu_dbm_open (db, flags, permissions);
307 if (rc)
308 {
309 mu_diag_funcall (MU_DIAG_ERROR, "mu_dbm_open",
310 db_name, rc);
311 exit (EX_SOFTWARE);
312 }
313
314 if (uid == 0)
315 return db;
316
317 rc = mu_dbm_get_fd (db, &fd, NULL);
318 if (rc)
319 {
320 mu_diag_funcall (MU_DIAG_ERROR, "mu_dbm_get_fd",
321 db_name, rc);
322 exit (EX_SOFTWARE);
323 }
324
325 if (fstat (fd, &sb))
326 {
327 mu_diag_funcall (MU_DIAG_ERROR, "fstat",
328 db_name, errno);
329 exit (EX_SOFTWARE);
330 }
331
332 if (sb.st_uid == uid)
333 {
334 if (my_file)
335 *my_file = 1;
336 return db;
337 }
338 if (my_file)
339 *my_file = 0;
340
261 if (ap->username) 341 if (ap->username)
262 { 342 {
263 mu_error (_("Only the file owner can use --username")); 343 mu_error (_("Only the file owner can use --username"));
...@@ -273,41 +353,36 @@ check_user_perm (int action, struct action_data *ap) ...@@ -273,41 +353,36 @@ check_user_perm (int action, struct action_data *ap)
273 if (!pw) 353 if (!pw)
274 exit (EX_OSERR); 354 exit (EX_OSERR);
275 ap->username = pw->pw_name; 355 ap->username = pw->pw_name;
276 return 1; 356 return db;
277 } 357 }
278 358
279 static void 359 static void
280 print_entry (mu_stream_t str, DBM_DATUM key, DBM_DATUM contents) 360 print_entry (mu_stream_t str, struct mu_dbm_datum const *key,
361 struct mu_dbm_datum const *contents)
281 { 362 {
282 if (compatibility_option) 363 if (compatibility_option)
283 mu_stream_printf (str, "%.*s: %.*s\n", 364 mu_stream_printf (str, "%.*s: %.*s\n",
284 (int) MU_DATUM_SIZE (key), 365 (int) key->mu_dsize,
285 (char*) MU_DATUM_PTR (key), 366 (char*) key->mu_dptr,
286 (int) MU_DATUM_SIZE (contents), 367 (int) contents->mu_dsize,
287 (char*) MU_DATUM_PTR (contents)); 368 (char*) contents->mu_dptr);
288 else 369 else
289 mu_stream_printf (str, "%.*s %.*s\n", 370 mu_stream_printf (str, "%.*s %.*s\n",
290 (int) MU_DATUM_SIZE (key), 371 (int) key->mu_dsize,
291 (char*) MU_DATUM_PTR (key), 372 (char*) key->mu_dptr,
292 (int) MU_DATUM_SIZE (contents), 373 (int) contents->mu_dsize,
293 (char*) MU_DATUM_PTR (contents)); 374 (char*) contents->mu_dptr);
294 } 375 }
295 376
296 int 377 int
297 action_list (struct action_data *ap) 378 action_list (struct action_data *ap)
298 { 379 {
299 mu_stream_t str; 380 mu_stream_t str;
300 DBM_FILE db; 381 mu_dbm_file_t db;
301 DBM_DATUM key; 382 struct mu_dbm_datum key, contents;
302 DBM_DATUM contents; 383 int rc;
303 384
304 check_user_perm (ACT_LIST, ap); 385 db = open_db_file (ACT_LIST, ap, NULL);
305 if (mu_dbm_open (ap->input_name, &db, MU_STREAM_READ, 0))
306 {
307 mu_error (_("cannot open file %s: %s"),
308 ap->input_name, mu_strerror (errno));
309 return 1;
310 }
311 386
312 if (ap->output_name) 387 if (ap->output_name)
313 { 388 {
...@@ -331,32 +406,47 @@ action_list (struct action_data *ap) ...@@ -331,32 +406,47 @@ action_list (struct action_data *ap)
331 { 406 {
332 memset (&key, 0, sizeof key); 407 memset (&key, 0, sizeof key);
333 memset (&contents, 0, sizeof contents); 408 memset (&contents, 0, sizeof contents);
334 MU_DATUM_PTR (key) = ap->username; 409 key.mu_dptr = ap->username;
335 MU_DATUM_SIZE (key) = strlen (ap->username); 410 key.mu_dsize = strlen (ap->username);
336 if (mu_dbm_fetch (db, key, &contents)) 411 rc = mu_dbm_fetch (db, &key, &contents);
412 if (rc == MU_ERR_NOENT)
337 { 413 {
338 mu_error (_("no such user: %s"), ap->username); 414 mu_error (_("no such user: %s"), ap->username);
339 } 415 }
416 else if (rc)
417 {
418 mu_error (_("database fetch error: %s"), mu_dbm_strerror (db));
419 exit (EX_UNAVAILABLE);
420 }
340 else 421 else
341 { 422 {
342 print_entry (str, key, contents); 423 print_entry (str, &key, &contents);
343 mu_dbm_datum_free (&contents); 424 mu_dbm_datum_free (&contents);
344 } 425 }
345 } 426 }
346 else 427 else
347 { 428 {
348 for (key = mu_dbm_firstkey (db); MU_DATUM_PTR(key); 429 memset (&key, 0, sizeof key);
349 key = mu_dbm_nextkey (db, key)) 430 for (rc = mu_dbm_firstkey (db, &key); rc == 0;
431 rc = mu_dbm_nextkey (db, &key))
350 { 432 {
351 memset (&contents, 0, sizeof contents); 433 memset (&contents, 0, sizeof contents);
352 mu_dbm_fetch (db, key, &contents); 434 rc = mu_dbm_fetch (db, &key, &contents);
353 print_entry (str, key, contents); 435 if (rc == 0)
354 mu_dbm_datum_free (&contents); 436 {
437 print_entry (str, &key, &contents);
438 mu_dbm_datum_free (&contents);
439 }
440 else
441 {
442 mu_error (_("database fetch error: %s"), mu_dbm_strerror (db));
443 exit (EX_UNAVAILABLE);
444 }
445 mu_dbm_datum_free (&key);
355 } 446 }
356 } 447 }
357 448
358 mu_dbm_close (db); 449 mu_dbm_destroy (&db);
359 mu_stream_destroy (&str);
360 return 0; 450 return 0;
361 } 451 }
362 452
...@@ -365,9 +455,8 @@ action_create (struct action_data *ap) ...@@ -365,9 +455,8 @@ action_create (struct action_data *ap)
365 { 455 {
366 int rc; 456 int rc;
367 mu_stream_t in; 457 mu_stream_t in;
368 DBM_FILE db; 458 mu_dbm_file_t db;
369 DBM_DATUM key; 459 struct mu_dbm_datum key, contents;
370 DBM_DATUM contents;
371 char *buf = NULL; 460 char *buf = NULL;
372 size_t size = 0, len; 461 size_t size = 0, len;
373 int line = 0; 462 int line = 0;
...@@ -399,12 +488,8 @@ action_create (struct action_data *ap) ...@@ -399,12 +488,8 @@ action_create (struct action_data *ap)
399 488
400 if (!ap->output_name) 489 if (!ap->output_name)
401 ap->output_name = APOP_PASSFILE; 490 ap->output_name = APOP_PASSFILE;
402 if (mu_dbm_open (ap->output_name, &db, MU_STREAM_CREAT, permissions)) 491
403 { 492 db = open_db_file (ACT_CREATE, ap, NULL);
404 mu_error (_("cannot create database %s: %s"),
405 ap->output_name, mu_strerror (errno));
406 return 1;
407 }
408 493
409 line = 0; 494 line = 0;
410 while ((rc = mu_stream_getline (in, &buf, &size, &len)) == 0 495 while ((rc = mu_stream_getline (in, &buf, &size, &len)) == 0
...@@ -435,20 +520,25 @@ action_create (struct action_data *ap) ...@@ -435,20 +520,25 @@ action_create (struct action_data *ap)
435 520
436 memset (&key, 0, sizeof key); 521 memset (&key, 0, sizeof key);
437 memset (&contents, 0, sizeof contents); 522 memset (&contents, 0, sizeof contents);
438 MU_DATUM_PTR (key) = str; 523 key.mu_dptr = str;
439 MU_DATUM_SIZE (key) = strlen (str); 524 key.mu_dsize = strlen (str);
440 MU_DATUM_PTR (contents) = pass; 525 contents.mu_dptr = pass;
441 MU_DATUM_SIZE (contents) = strlen (pass); 526 contents.mu_dsize = strlen (pass);
442 527
443 if (mu_dbm_insert (db, key, contents, 1)) 528 rc = mu_dbm_store (db, &key, &contents, 1);
444 mu_error (_("%s:%d: cannot store datum"), ap->input_name, line); 529 if (rc)
530 mu_error (_("%s:%d: cannot store datum: %s"),
531 ap->input_name, line,
532 rc == MU_ERR_FAILURE ?
533 mu_dbm_strerror (db) : mu_strerror (rc));
445 } 534 }
446 free (buf); 535 free (buf);
447 mu_dbm_close (db); 536 mu_dbm_destroy (&db);
448 mu_stream_destroy (&in); 537 mu_stream_destroy (&in);
449 return 0; 538 return 0;
450 } 539 }
451 540
541 /*FIXME
452 int 542 int
453 open_io (int action, struct action_data *ap, DBM_FILE *db, int *not_owner) 543 open_io (int action, struct action_data *ap, DBM_FILE *db, int *not_owner)
454 { 544 {
...@@ -463,6 +553,7 @@ 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)
463 } 553 }
464 return 0; 554 return 0;
465 } 555 }
556 */
466 557
467 void 558 void
468 fill_pass (struct action_data *ap) 559 fill_pass (struct action_data *ap)
...@@ -527,9 +618,8 @@ fill_pass (struct action_data *ap) ...@@ -527,9 +618,8 @@ fill_pass (struct action_data *ap)
527 int 618 int
528 action_add (struct action_data *ap) 619 action_add (struct action_data *ap)
529 { 620 {
530 DBM_FILE db; 621 mu_dbm_file_t db;
531 DBM_DATUM key; 622 struct mu_dbm_datum key, contents;
532 DBM_DATUM contents;
533 int rc; 623 int rc;
534 624
535 if (!ap->username) 625 if (!ap->username)
...@@ -538,31 +628,32 @@ action_add (struct action_data *ap) ...@@ -538,31 +628,32 @@ action_add (struct action_data *ap)
538 return 1; 628 return 1;
539 } 629 }
540 630
541 if (open_io (ACT_ADD, ap, &db, NULL)) 631 db = open_db_file (ACT_ADD, ap, NULL);
542 return 1;
543 632
544 fill_pass (ap); 633 fill_pass (ap);
545 634
546 memset (&key, 0, sizeof key); 635 memset (&key, 0, sizeof key);
547 memset (&contents, 0, sizeof contents); 636 memset (&contents, 0, sizeof contents);
548 MU_DATUM_PTR (key) = ap->username; 637 key.mu_dptr = ap->username;
549 MU_DATUM_SIZE (key) = strlen (ap->username); 638 key.mu_dsize = strlen (ap->username);
550 MU_DATUM_PTR (contents) = ap->passwd; 639 contents.mu_dptr = ap->passwd;
551 MU_DATUM_SIZE (contents) = strlen (ap->passwd); 640 contents.mu_dsize = strlen (ap->passwd);
552 641
553 rc = mu_dbm_insert (db, key, contents, 1); 642 rc = mu_dbm_store (db, &key, &contents, 1);
554 if (rc) 643 if (rc)
555 mu_error (_("cannot store datum")); 644 mu_error (_("cannot store datum: %s"),
645 rc == MU_ERR_FAILURE ?
646 mu_dbm_strerror (db) : mu_strerror (rc));
556 647
557 mu_dbm_close (db); 648 mu_dbm_destroy (&db);
558 return rc; 649 return rc;
559 } 650 }
560 651
561 int 652 int
562 action_delete (struct action_data *ap) 653 action_delete (struct action_data *ap)
563 { 654 {
564 DBM_FILE db; 655 mu_dbm_file_t db;
565 DBM_DATUM key; 656 struct mu_dbm_datum key;
566 int rc; 657 int rc;
567 658
568 if (!ap->username) 659 if (!ap->username)
...@@ -571,56 +662,64 @@ action_delete (struct action_data *ap) ...@@ -571,56 +662,64 @@ action_delete (struct action_data *ap)
571 return 1; 662 return 1;
572 } 663 }
573 664
574 if (open_io (ACT_DELETE, ap, &db, NULL)) 665 db = open_db_file (ACT_DELETE, ap, NULL);
575 return 1; 666
576 667 memset (&key, 0, sizeof key);
577 MU_DATUM_PTR (key) = ap->username; 668 key.mu_dptr = ap->username;
578 MU_DATUM_SIZE (key) = strlen (ap->username); 669 key.mu_dsize = strlen (ap->username);
579 670
580 rc = mu_dbm_delete (db, key); 671 rc = mu_dbm_delete (db, &key);
581 if (rc) 672 if (rc)
582 mu_error (_("cannot remove record for %s"), ap->username); 673 mu_error (_("cannot remove record for %s: %s"),
674 ap->username,
675 rc == MU_ERR_FAILURE ?
676 mu_dbm_strerror (db) : mu_strerror (rc));
583 677
584 mu_dbm_close (db); 678 mu_dbm_destroy (&db);
585 return rc; 679 return rc;
586 } 680 }
587 681
588 int 682 int
589 action_chpass (struct action_data *ap) 683 action_chpass (struct action_data *ap)
590 { 684 {
591 DBM_FILE db; 685 mu_dbm_file_t db;
592 DBM_DATUM key; 686 struct mu_dbm_datum key, contents;
593 DBM_DATUM contents;
594 int rc; 687 int rc;
595 int not_owner; 688 int my_file;
596 689
597 if (open_io (ACT_CHPASS, ap, &db, &not_owner)) 690 db = open_db_file (ACT_CHPASS, ap, &my_file);
598 return 1;
599 691
600 if (!ap->username) 692 if (!ap->username)
601 { 693 {
602 mu_error (_("missing username")); 694 struct passwd *pw = getpwuid (getuid ());
603 return 1; 695 ap->username = pw->pw_name;
696 printf ("Changing password for %s\n", ap->username);
604 } 697 }
605 698
606 memset (&key, 0, sizeof key); 699 memset (&key, 0, sizeof key);
607 memset (&contents, 0, sizeof contents); 700 memset (&contents, 0, sizeof contents);
608 701
609 MU_DATUM_PTR (key) = ap->username; 702 key.mu_dptr = ap->username;
610 MU_DATUM_SIZE (key) = strlen (ap->username); 703 key.mu_dsize = strlen (ap->username);
611 if (mu_dbm_fetch (db, key, &contents)) 704 rc = mu_dbm_fetch (db, &key, &contents);
705 if (rc == MU_ERR_NOENT)
612 { 706 {
613 mu_error (_("no such user: %s"), ap->username); 707 mu_error (_("no such user: %s"), ap->username);
614 return 1; 708 return 1;
615 } 709 }
616 710 else if (rc)
617 if (not_owner) 711 {
712 mu_error (_("database fetch error: %s"), mu_dbm_strerror (db));
713 exit (EX_UNAVAILABLE);
714 }
715
716 if (!my_file)
618 { 717 {
619 char *oldpass, *p; 718 char *oldpass, *p;
620 719
621 oldpass = xmalloc (MU_DATUM_SIZE (contents) + 1); 720 oldpass = xmalloc (contents.mu_dsize + 1);
622 memcpy (oldpass, MU_DATUM_PTR (contents), MU_DATUM_SIZE (contents)); 721 memcpy (oldpass, contents.mu_dptr, contents.mu_dsize);
623 oldpass[MU_DATUM_SIZE (contents)] = 0; 722 oldpass[contents.mu_dsize] = 0;
624 p = getpass (_("Old Password:")); 723 p = getpass (_("Old Password:"));
625 if (!p) 724 if (!p)
626 return 1; 725 return 1;
...@@ -634,32 +733,49 @@ action_chpass (struct action_data *ap) ...@@ -634,32 +733,49 @@ action_chpass (struct action_data *ap)
634 fill_pass (ap); 733 fill_pass (ap);
635 734
636 mu_dbm_datum_free (&contents); 735 mu_dbm_datum_free (&contents);
637 MU_DATUM_PTR (contents) = ap->passwd; 736 contents.mu_dptr = ap->passwd;
638 MU_DATUM_SIZE (contents) = strlen (ap->passwd); 737 contents.mu_dsize = strlen (ap->passwd);
639 rc = mu_dbm_insert (db, key, contents, 1); 738 rc = mu_dbm_store (db, &key, &contents, 1);
640 if (rc) 739 if (rc)
641 mu_error (_("cannot replace datum")); 740 mu_error (_("cannot replace datum: %s"),
741 rc == MU_ERR_FAILURE ?
742 mu_dbm_strerror (db) : mu_strerror (rc));
642 743
643 mu_dbm_close (db); 744 mu_dbm_destroy (&db);
644 return rc; 745 return rc;
645 } 746 }
646 747
647 void 748 void
648 popauth_version (FILE *stream, struct argp_state *state) 749 popauth_version (FILE *stream, struct argp_state *state)
649 { 750 {
650 #if defined(WITH_GDBM) 751 mu_iterator_t itr;
651 # define FORMAT "GDBM" 752 int rc;
652 #elif defined(WITH_BDB) 753
653 # define FORMAT "Berkeley DB"
654 #elif defined(WITH_NDBM)
655 # define FORMAT "NDBM"
656 #elif defined(WITH_OLD_DBM)
657 # define FORMAT "Old DBM"
658 #elif defined(WITH_TOKYOCABINET)
659 # define FORMAT "Tokyo Cabinet"
660 #endif
661 mu_program_version_hook (stream, state); 754 mu_program_version_hook (stream, state);
662 fprintf (stream, _("Database format: %s\n"), FORMAT); 755 fprintf (stream, _("Database formats: "));
663 fprintf (stream, _("Database location: %s\n"), APOP_PASSFILE); 756
757 rc = mu_dbm_impl_iterator (&itr);
758 if (rc)
759 {
760 fprintf (stream, "%s\n", _("unknown"));
761 mu_error ("%s", mu_strerror (rc));
762 }
763 else
764 {
765 int i;
766 for (mu_iterator_first (itr), i = 0; !mu_iterator_is_done (itr);
767 mu_iterator_next (itr), i++)
768 {
769 struct mu_dbm_impl *impl;
770
771 mu_iterator_current (itr, (void**)&impl);
772 if (i)
773 fprintf (stream, ", ");
774 fprintf (stream, "%s", impl->_dbm_name);
775 }
776 fputc ('\n', stream);
777 mu_iterator_destroy (&itr);
778 }
779 fprintf (stream, _("Default database location: %s\n"), APOP_PASSFILE);
664 exit (EX_OK); 780 exit (EX_OK);
665 } 781 }
......