]>
Commit | Line | Data |
---|---|---|
26761c28 | 1 | /* Mail alias file parser in nss_db module. |
74015205 | 2 | Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. |
26761c28 UD |
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> | |
5148d49f | 24 | #include <db.h> |
26761c28 UD |
25 | #include <errno.h> |
26 | #include <fcntl.h> | |
5107cf1d | 27 | #include <bits/libc-lock.h> |
26761c28 UD |
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; | |
5148d49f | 47 | int err; |
26761c28 UD |
48 | |
49 | if (db == NULL) | |
50 | { | |
5148d49f UD |
51 | err = __nss_db_open (_PATH_VARDB "aliases.db", DB_BTREE, DB_RDONLY, 0, |
52 | NULL, NULL, &db); | |
26761c28 | 53 | |
5148d49f UD |
54 | if (err != 0) |
55 | { | |
56 | __set_errno (err); | |
57 | status = NSS_STATUS_UNAVAIL; | |
58 | } | |
3996f34b UD |
59 | else |
60 | { | |
61 | /* We have to make sure the file is `closed on exec'. */ | |
5148d49f | 62 | int fd; |
3996f34b UD |
63 | int result, flags; |
64 | ||
5148d49f UD |
65 | err = db->fd (db, &fd); |
66 | if (err != 0) | |
67 | { | |
68 | __set_errno (err); | |
69 | result = -1; | |
70 | } | |
71 | else | |
72 | result = flags = fcntl (fd, F_GETFD, 0); | |
3996f34b UD |
73 | if (result >= 0) |
74 | { | |
75 | flags |= FD_CLOEXEC; | |
5148d49f | 76 | result = fcntl (fd, F_SETFD, flags); |
3996f34b UD |
77 | } |
78 | if (result < 0) | |
79 | { | |
80 | /* Something went wrong. Close the stream and return a | |
81 | failure. */ | |
5148d49f | 82 | db->close (db, 0); |
3996f34b UD |
83 | db = NULL; |
84 | status = NSS_STATUS_UNAVAIL; | |
85 | } | |
86 | } | |
26761c28 UD |
87 | } |
88 | ||
89 | /* Remember STAYOPEN flag. */ | |
90 | if (db != NULL) | |
91 | keep_db |= stayopen; | |
92 | ||
93 | return status; | |
94 | } | |
95 | ||
96 | ||
97 | /* Thread-safe, exported version of that. */ | |
98 | enum nss_status | |
99 | _nss_db_setaliasent (int stayopen) | |
100 | { | |
101 | enum nss_status status; | |
102 | ||
103 | __libc_lock_lock (lock); | |
104 | ||
105 | status = internal_setent (stayopen); | |
106 | ||
107 | /* Reset the sequential index. */ | |
108 | entidx = 0; | |
109 | ||
110 | __libc_lock_unlock (lock); | |
111 | ||
112 | return status; | |
113 | } | |
114 | ||
115 | ||
116 | /* Close the database file. */ | |
117 | static void | |
118 | internal_endent (void) | |
119 | { | |
120 | if (db != NULL) | |
121 | { | |
5148d49f | 122 | db->close (db, 0); |
26761c28 UD |
123 | db = NULL; |
124 | } | |
125 | } | |
126 | ||
127 | ||
128 | /* Thread-safe, exported version of that. */ | |
129 | enum nss_status | |
130 | _nss_db_endaliasent (void) | |
131 | { | |
132 | __libc_lock_lock (lock); | |
133 | ||
134 | internal_endent (); | |
135 | ||
136 | /* Reset STAYOPEN flag. */ | |
137 | keep_db = 0; | |
138 | ||
139 | __libc_lock_unlock (lock); | |
140 | ||
141 | return NSS_STATUS_SUCCESS; | |
142 | } | |
143 | \f | |
144 | /* We provide the parse function here. The parser in libnss_files | |
145 | cannot be used. The generation of the db file already resolved all | |
146 | :include: statements so we simply have to parse the list and store | |
147 | the result. */ | |
148 | static enum nss_status | |
5148d49f | 149 | lookup (DBT *key, struct aliasent *result, char *buffer, |
d71b808a | 150 | size_t buflen, int *errnop) |
26761c28 UD |
151 | { |
152 | enum nss_status status; | |
153 | DBT value; | |
154 | ||
155 | /* Open the database. */ | |
156 | status = internal_setent (keep_db); | |
157 | if (status != NSS_STATUS_SUCCESS) | |
5148d49f UD |
158 | { |
159 | *errnop = errno; | |
160 | return status; | |
161 | } | |
26761c28 | 162 | |
5148d49f UD |
163 | value.flags = 0; |
164 | if (db->get (db, NULL, key, &value, 0) == 0) | |
26761c28 UD |
165 | { |
166 | const char *src = value.data; | |
167 | ||
168 | result->alias_members_len = 0; | |
169 | ||
170 | /* We now have to fill the BUFFER with all the information. */ | |
171 | if (buflen < key->size + 1) | |
172 | { | |
173 | no_more_room: | |
d71b808a | 174 | *errnop = ERANGE; |
26761c28 UD |
175 | return NSS_STATUS_TRYAGAIN; |
176 | } | |
177 | ||
178 | if (status == NSS_STATUS_SUCCESS) | |
179 | { | |
180 | char *cp; | |
181 | size_t cnt; | |
182 | ||
183 | buffer = stpncpy (buffer, key->data, key->size) + 1; | |
184 | buflen -= key->size + 1; | |
185 | ||
186 | while (*src != '\0') | |
187 | { | |
188 | const char *end, *upto; | |
189 | while (isspace (*src)) | |
190 | ++src; | |
191 | ||
192 | end = strchr (src, ','); | |
193 | if (end == NULL) | |
194 | end = strchr (src, '\0'); | |
195 | for (upto = end; upto > src && isspace (upto[-1]); --upto); | |
196 | ||
197 | if (upto != src) | |
198 | { | |
199 | if ((upto - src) + __alignof__ (char *) > buflen) | |
200 | goto no_more_room; | |
201 | buffer = stpncpy (buffer, src, upto - src) + 1; | |
202 | buflen -= (upto - src) + __alignof (char *); | |
203 | ++result->alias_members_len; | |
204 | } | |
205 | src = end + (*end != '\0'); | |
206 | } | |
207 | ||
208 | /* Now prepare the return. Provide string pointers for the | |
209 | currently selected aliases. */ | |
210 | ||
211 | /* Adjust the pointer so it is aligned for storing pointers. */ | |
212 | buffer += __alignof__ (char *) - 1; | |
213 | buffer -= ((buffer - (char *) 0) % __alignof__ (char *)); | |
214 | result->alias_members = (char **) buffer; | |
215 | ||
216 | /* Compute addresses of alias entry strings. */ | |
217 | cp = result->alias_name; | |
218 | for (cnt = 0; cnt < result->alias_members_len; ++cnt) | |
219 | { | |
220 | cp = strchr (cp, '\0') + 1; | |
221 | result->alias_members[cnt] = cp; | |
222 | } | |
223 | ||
224 | status = (result->alias_members_len == 0 | |
225 | ? NSS_STATUS_RETURN : NSS_STATUS_SUCCESS); | |
226 | } | |
227 | } | |
228 | else | |
229 | status = NSS_STATUS_NOTFOUND; | |
230 | ||
231 | if (! keep_db) | |
232 | internal_endent (); | |
233 | ||
234 | return status; | |
235 | } | |
236 | \f | |
237 | enum nss_status | |
d71b808a UD |
238 | _nss_db_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen, |
239 | int *errnop) | |
26761c28 | 240 | { |
74015205 | 241 | /* Return next entry in alias file. */ |
26761c28 UD |
242 | enum nss_status status; |
243 | char buf[20]; | |
244 | DBT key; | |
245 | ||
246 | __libc_lock_lock (lock); | |
74015205 | 247 | key.size = snprintf (key.data = buf, sizeof buf, "0%u", entidx++); |
5148d49f | 248 | key.flags = 0; |
d71b808a | 249 | status = lookup (&key, result, buffer, buflen, errnop); |
5148d49f UD |
250 | if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE) |
251 | /* Give the user a chance to get the same entry with a larger buffer. */ | |
252 | --entidx; | |
26761c28 UD |
253 | __libc_lock_unlock (lock); |
254 | ||
255 | return status; | |
256 | } | |
257 | ||
258 | ||
259 | enum nss_status | |
260 | _nss_db_getaliasbyname_r (const char *name, struct aliasent *result, | |
d71b808a | 261 | char *buffer, size_t buflen, int *errnop) |
26761c28 UD |
262 | { |
263 | DBT key; | |
264 | enum nss_status status; | |
265 | ||
266 | key.size = 1 + strlen (name); | |
267 | ||
268 | key.data = __alloca (key.size); | |
269 | ((char *) key.data)[0] = '.'; | |
270 | memcpy (&((char *) key.data)[1], name, key.size - 1); | |
5148d49f | 271 | key.flags = 0; |
26761c28 UD |
272 | |
273 | __libc_lock_lock (lock); | |
d71b808a | 274 | status = lookup (&key, result, buffer, buflen, errnop); |
26761c28 UD |
275 | __libc_lock_unlock (lock); |
276 | ||
277 | return status; | |
278 | } |