(internal_setent): Use __dbopen instead of dbopen.
[kopensolaris-gnu/glibc.git] / nss / nss_db / db-alias.c
1 /* Mail alias file parser in nss_db module.
2    Copyright (C) 1996 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include <aliases.h>
22 #include <alloca.h>
23 #include <ctype.h>
24 #include <db.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <libc-lock.h>
28 #include <paths.h>
29 #include <string.h>
30
31 #include "nsswitch.h"
32
33 /* Locks the static variables in this file.  */
34 __libc_lock_define_initialized (static, lock)
35 \f
36 /* Maintenance of the shared handle open on the database.  */
37
38 static DB *db;
39 static int keep_db;
40 static unsigned int entidx;     /* Index for `getaliasent_r'. */
41
42 /* Open database file if not already opened.  */
43 static enum nss_status
44 internal_setent (int stayopen)
45 {
46   enum nss_status status = NSS_STATUS_SUCCESS;
47
48   if (db == NULL)
49     {
50       db = __dbopen (_PATH_VARDB "aliases.db", O_RDONLY, 0, DB_BTREE, NULL);
51
52       if (db == NULL)
53         status = NSS_STATUS_UNAVAIL;
54     }
55
56   /* Remember STAYOPEN flag.  */
57   if (db != NULL)
58     keep_db |= stayopen;
59
60   return status;
61 }
62
63
64 /* Thread-safe, exported version of that.  */
65 enum nss_status
66 _nss_db_setaliasent (int stayopen)
67 {
68   enum nss_status status;
69
70   __libc_lock_lock (lock);
71
72   status = internal_setent (stayopen);
73
74   /* Reset the sequential index.  */
75   entidx = 0;
76
77   __libc_lock_unlock (lock);
78
79   return status;
80 }
81
82
83 /* Close the database file.  */
84 static void
85 internal_endent (void)
86 {
87   if (db != NULL)
88     {
89       (*db->close) (db);
90       db = NULL;
91     }
92 }
93
94
95 /* Thread-safe, exported version of that.  */
96 enum nss_status
97 _nss_db_endaliasent (void)
98 {
99   __libc_lock_lock (lock);
100
101   internal_endent ();
102
103   /* Reset STAYOPEN flag.  */
104   keep_db = 0;
105
106   __libc_lock_unlock (lock);
107
108   return NSS_STATUS_SUCCESS;
109 }
110 \f
111 /* We provide the parse function here.  The parser in libnss_files
112    cannot be used.  The generation of the db file already resolved all
113    :include: statements so we simply have to parse the list and store
114    the result.  */
115 static enum nss_status
116 lookup (const DBT *key, struct aliasent *result, char *buffer,
117             size_t buflen)
118 {
119   enum nss_status status;
120   DBT value;
121
122   /* Open the database.  */
123   status = internal_setent (keep_db);
124   if (status != NSS_STATUS_SUCCESS)
125     return status;
126
127   if ((*db->get) (db, key, &value, 0) == 0)
128     {
129       const char *src = value.data;
130
131       result->alias_members_len = 0;
132
133       /* We now have to fill the BUFFER with all the information. */
134       if (buflen < key->size + 1)
135         {
136         no_more_room:
137           __set_errno (ERANGE);
138           return NSS_STATUS_TRYAGAIN;
139         }
140
141       if (status == NSS_STATUS_SUCCESS)
142         {
143           char *cp;
144           size_t cnt;
145
146           buffer = stpncpy (buffer, key->data, key->size) + 1;
147           buflen -= key->size + 1;
148
149           while (*src != '\0')
150             {
151               const char *end, *upto;
152               while (isspace (*src))
153                 ++src;
154
155               end = strchr (src, ',');
156               if (end == NULL)
157                 end = strchr (src, '\0');
158               for (upto = end; upto > src && isspace (upto[-1]); --upto);
159
160               if (upto != src)
161                 {
162                   if ((upto - src) + __alignof__ (char *) > buflen)
163                     goto no_more_room;
164                   buffer = stpncpy (buffer, src, upto - src) + 1;
165                   buflen -= (upto - src) + __alignof (char *);
166                   ++result->alias_members_len;
167                 }
168               src = end + (*end != '\0');
169             }
170
171           /* Now prepare the return.  Provide string pointers for the
172              currently selected aliases.  */
173
174           /* Adjust the pointer so it is aligned for storing pointers.  */
175           buffer += __alignof__ (char *) - 1;
176           buffer -= ((buffer - (char *) 0) % __alignof__ (char *));
177           result->alias_members = (char **) buffer;
178
179           /* Compute addresses of alias entry strings.  */
180           cp = result->alias_name;
181           for (cnt = 0; cnt < result->alias_members_len; ++cnt)
182             {
183               cp = strchr (cp, '\0') + 1;
184               result->alias_members[cnt] = cp;
185             }
186
187           status = (result->alias_members_len == 0
188                     ? NSS_STATUS_RETURN : NSS_STATUS_SUCCESS);
189         }
190     }
191   else
192     status = NSS_STATUS_NOTFOUND;
193
194   if (! keep_db)
195     internal_endent ();
196
197   return status;
198 }
199 \f
200 enum nss_status
201 _nss_db_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen)
202 {
203   /* Return next entry in host file.  */
204   enum nss_status status;
205   char buf[20];
206   DBT key;
207
208   __libc_lock_lock (lock);
209   key.size = 1 + snprintf (key.data = buf, sizeof buf, "0%u", entidx++);
210   status = lookup (&key, result, buffer, buflen);
211   __libc_lock_unlock (lock);
212
213   return status;
214 }
215
216
217 enum nss_status
218 _nss_db_getaliasbyname_r (const char *name, struct aliasent *result,
219                           char *buffer, size_t buflen)
220 {
221   DBT key;
222   enum nss_status status;
223
224   key.size = 1 + strlen (name);
225
226   key.data = __alloca (key.size);
227   ((char *) key.data)[0] = '.';
228   memcpy (&((char *) key.data)[1], name, key.size - 1);
229
230   __libc_lock_lock (lock);
231   status = lookup (&key, result, buffer, buflen);
232   __libc_lock_unlock (lock);
233
234   return status;
235 }