/* gdbm.c This file is part of GNU Anubis. Copyright (C) 2003-2024 The Anubis Team. GNU Anubis is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Anubis is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Anubis. If not, see . */ #include "headers.h" #ifdef HAVE_LIBGDBM #include /* Format of an GDBM record: char *key Username char *value The colon-separated list of the following values: password,username,rc-file The last two items are optional */ static int db_gdbm_open (void **dp, ANUBIS_URL * url, enum anubis_db_mode mode, char const **errp) { GDBM_FILE dbf; int flags; char *path; switch (mode) { case anubis_db_rdonly: flags = GDBM_READER; break; case anubis_db_rdwr: flags = GDBM_WRCREAT; break; default: flags = 0; } path = anubis_url_full_path (url); dbf = gdbm_open (path, 0, flags, 0644, NULL); free (path); if (!dbf) { *errp = gdbm_strerror (gdbm_errno); return ANUBIS_DB_FAIL; } *dp = dbf; return ANUBIS_DB_SUCCESS; } static int db_gdbm_close (void *d) { gdbm_close (d); return ANUBIS_DB_SUCCESS; } static void gdbm_content_to_record (char *keystr, datum content, ANUBIS_USER * rec) { char *p; char *text = xmalloc (content.dsize + 1); memcpy (text, content.dptr, content.dsize); text[content.dsize] = 0; rec->smtp_authid = strdup (keystr); p = strtok (text, ","); if (p) { rec->smtp_passwd = strdup (p); p = strtok (NULL, ","); if (p) { rec->username = strdup (p); p = strtok (NULL, ","); if (p) rec->rcfile_name = strdup (p); } free (text); } else rec->smtp_passwd = text; } static int db_gdbm_get (void *d, const char *keystr, ANUBIS_USER * rec, int *errp) { datum key, content; key.dptr = (char *) keystr; key.dsize = strlen (keystr); content = gdbm_fetch ((GDBM_FILE) d, key); if (content.dptr == NULL) return ANUBIS_DB_NOT_FOUND; memset (rec, 0, sizeof *rec); gdbm_content_to_record ((char *) keystr, content, rec); free (content.dptr); return ANUBIS_DB_SUCCESS; } static int db_gdbm_list (void *d, ANUBIS_LIST list, int *ecode) { datum key, content; key = gdbm_firstkey ((GDBM_FILE) d); while (key.dptr) { datum nextkey; content = gdbm_fetch ((GDBM_FILE) d, key); if (content.dptr) { ANUBIS_USER *rec = xmalloc (sizeof (*rec)); char *keyval = xmalloc (key.dsize + 1); memcpy (keyval, key.dptr, key.dsize); keyval[key.dsize] = 0; gdbm_content_to_record (keyval, content, rec); free (keyval); list_append (list, rec); } nextkey = gdbm_nextkey ((GDBM_FILE) d, key); free (key.dptr); key = nextkey; } return ANUBIS_DB_SUCCESS; } static int db_gdbm_put (void *d, const char *keystr, ANUBIS_USER * rec, int *errp) { size_t size, n; char *text; datum key, content; int rc; size = strlen (rec->smtp_passwd) + 1; if (rec->username) size += strlen (rec->username) + 1; if (rec->rcfile_name) { size += strlen (rec->rcfile_name); if (!rec->username) size += strlen (rec->smtp_authid) + 1; } text = xmalloc (size + 1); n = sprintf (text, "%s", rec->smtp_passwd); if (rec->username) n += sprintf (text + n, ",%s", rec->username); if (rec->rcfile_name) { if (!rec->username) n += sprintf (text + n, ",%s", rec->smtp_authid); n += sprintf (text + n, ",%s", rec->rcfile_name); } key.dptr = (char *) keystr; key.dsize = strlen (keystr); content.dptr = text; content.dsize = size; if (gdbm_store ((GDBM_FILE) d, key, content, GDBM_REPLACE)) { *errp = gdbm_errno; rc = ANUBIS_DB_FAIL; } else rc = ANUBIS_DB_SUCCESS; free (text); return rc; } static int db_gdbm_delete (void *d, const char *keystr, int *ecode) { int rc; datum key; key.dptr = (char *) keystr; key.dsize = strlen (keystr); if (gdbm_delete ((GDBM_FILE) d, key)) { *ecode = gdbm_errno; rc = ANUBIS_DB_FAIL; } else rc = ANUBIS_DB_SUCCESS; return rc; } static const char * db_gdbm_strerror (void *d, int rc) { return gdbm_strerror (rc); } void db_gdbm_init (void) { anubis_db_register ("gdbm", db_gdbm_open, db_gdbm_close, db_gdbm_get, db_gdbm_put, db_gdbm_delete, db_gdbm_list, db_gdbm_strerror); } #endif /* HAVE_LIBGDBM */ /* EOF */