1/* $Id$ */
2
3/***
4  This file is part of avahi.
5
6  avahi is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Lesser General Public License as
8  published by the Free Software Foundation; either version 2.1 of the
9  License, or (at your option) any later version.
10
11  avahi is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14  Public License for more details.
15
16  You should have received a copy of the GNU Lesser General Public
17  License along with avahi; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19  USA.
20***/
21
22#include <config.h>
23#ifdef HAVE_GDBM
24#include <gdbm.h>
25#endif
26#ifdef HAVE_DBM
27#include <ndbm.h>
28#include <fcntl.h>
29#endif
30#include <stdlib.h>
31#include <string.h>
32#include <locale.h>
33#include <stdio.h>
34
35#include <avahi-common/malloc.h>
36
37#include "stdb.h"
38
39#ifdef HAVE_GDBM
40static GDBM_FILE gdbm_file = NULL;
41#endif
42#ifdef HAVE_DBM
43static DBM *dbm_file = NULL;
44#endif
45static char *buffer = NULL;
46static char *enum_key = NULL;
47
48static int init(void) {
49
50#ifdef HAVE_GDBM
51    if (gdbm_file)
52        return 0;
53
54    if (!(gdbm_file = gdbm_open((char*) DATABASE_FILE, 0, GDBM_READER, 0, NULL)))
55        return -1;
56#endif
57#ifdef HAVE_DBM
58    if (dbm_file)
59        return 0;
60
61    if (!(dbm_file = dbm_open((char*) DATABASE_FILE, O_RDONLY, 0)))
62        return -1;
63#endif
64
65    return 0;
66}
67
68const char* stdb_lookup(const char *name) {
69    datum key, data;
70    const char *loc;
71
72    if (init() < 0)
73        goto fail;
74
75    data.dptr = NULL;
76    data.dsize = 0;
77
78    if ((loc = setlocale(LC_MESSAGES, NULL))) {
79        char k[256];
80
81        snprintf(k, sizeof(k), "%s[%s]", name, loc);
82        key.dptr = k;
83        key.dsize = strlen(k);
84#ifdef HAVE_GDBM
85        data = gdbm_fetch(gdbm_file, key);
86#endif
87#ifdef HAVE_DBM
88        data = dbm_fetch(dbm_file, key);
89#endif
90
91        if (!data.dptr) {
92            char l[32], *e;
93            snprintf(l, sizeof(l), "%s", loc);
94
95            if ((e = strchr(l, '@'))) {
96                *e = 0;
97                snprintf(k, sizeof(k), "%s[%s]", name, l);
98                key.dptr = k;
99                key.dsize = strlen(k);
100#ifdef HAVE_GDBM
101                data = gdbm_fetch(gdbm_file, key);
102#endif
103#ifdef HAVE_DBM
104                data = dbm_fetch(dbm_file, key);
105#endif
106            }
107
108            if (!data.dptr) {
109                if ((e = strchr(l, '_'))) {
110                    *e = 0;
111                    snprintf(k, sizeof(k), "%s[%s]", name, l);
112                    key.dptr = k;
113                    key.dsize = strlen(k);
114#ifdef HAVE_GDBM
115                    data = gdbm_fetch(gdbm_file, key);
116#endif
117#ifdef HAVE_DBM
118                    data = dbm_fetch(dbm_file, key);
119#endif
120                }
121            }
122        }
123    }
124
125    if (!data.dptr) {
126        key.dptr = (char*) name;
127        key.dsize = strlen(name);
128#ifdef HAVE_GDBM
129        data = gdbm_fetch(gdbm_file, key);
130#endif
131#ifdef HAVE_DBM
132        data = dbm_fetch(dbm_file, key);
133#endif
134    }
135
136    if (!data.dptr)
137        goto fail;
138
139    avahi_free(buffer);
140    buffer = avahi_strndup(data.dptr, data.dsize);
141    free(data.dptr);
142
143    return buffer;
144
145fail:
146
147    return name;
148}
149
150void stdb_shutdown(void) {
151#ifdef HAVE_GDBM
152    if (gdbm_file)
153        gdbm_close(gdbm_file);
154
155    gdbm_file = NULL;
156#endif
157#ifdef HAVE_DBM
158    if (dbm_file)
159        dbm_close(dbm_file);
160
161    dbm_file = NULL;
162#endif
163
164    avahi_free(buffer);
165    avahi_free(enum_key);
166
167    buffer = enum_key = NULL;
168}
169
170char *stdb_getent(void) {
171    datum key;
172
173    if (init() < 0)
174        return NULL;
175
176    for (;;) {
177
178        if (!enum_key) {
179#ifdef HAVE_GDBM
180            key = gdbm_firstkey(gdbm_file);
181#endif
182#ifdef HAVE_DBM
183            key = dbm_firstkey(dbm_file);
184#endif
185        } else {
186            key.dptr = enum_key;
187            key.dsize = strlen(enum_key);
188
189#ifdef HAVE_GDBM
190            key = gdbm_nextkey(gdbm_file, key);
191#endif
192#ifdef HAVE_DBM
193            key = dbm_nextkey(dbm_file);
194#endif
195        }
196
197        avahi_free(enum_key);
198        enum_key = NULL;
199
200        if (!key.dptr)
201            return NULL;
202
203        enum_key = avahi_strndup(key.dptr, key.dsize);
204        free(key.dptr);
205
206        if (!strchr(enum_key, '['))
207            return enum_key;
208    }
209}
210
211void stdb_setent(void) {
212    avahi_free(enum_key);
213    enum_key = NULL;
214}
215