]>
Commit | Line | Data |
---|---|---|
c8e82b4a UD |
1 | /* Copyright (C) 1997, 1998, 2001, 2002, 2003, 2005, 2006 |
2 | Free Software Foundation, Inc. | |
e61abf83 UD |
3 | This file is part of the GNU C Library. |
4 | Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
41bdb6e2 AJ |
7 | modify it under the terms of the GNU Lesser General Public |
8 | License as published by the Free Software Foundation; either | |
9 | version 2.1 of the License, or (at your option) any later version. | |
e61abf83 UD |
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 | |
41bdb6e2 | 14 | Lesser General Public License for more details. |
e61abf83 | 15 | |
41bdb6e2 | 16 | You should have received a copy of the GNU Lesser General Public |
59ba27a6 PE |
17 | License along with the GNU C Library; if not, see |
18 | <http://www.gnu.org/licenses/>. */ | |
e61abf83 | 19 | |
636e689e | 20 | #include <atomic.h> |
e61abf83 UD |
21 | #include <nss.h> |
22 | #include <errno.h> | |
23 | #include <ctype.h> | |
24 | #include <string.h> | |
25 | #include <aliases.h> | |
5107cf1d | 26 | #include <bits/libc-lock.h> |
e61abf83 | 27 | #include <rpcsvc/nis.h> |
e61abf83 UD |
28 | |
29 | #include "nss-nisplus.h" | |
30 | ||
31 | __libc_lock_define_initialized (static, lock) | |
32 | ||
fc9f33e3 UD |
33 | static nis_result *result; |
34 | static u_long next_entry; | |
35 | static nis_name tablename_val; | |
636e689e | 36 | static size_t tablename_len; |
e61abf83 | 37 | |
3fc044a1 UD |
38 | #define NISENTRYVAL(idx, col, res) \ |
39 | (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_val) | |
e61abf83 | 40 | |
3fc044a1 UD |
41 | #define NISENTRYLEN(idx, col, res) \ |
42 | (NIS_RES_OBJECT (res)[idx].EN_data.en_cols.en_cols_val[col].ec_value.ec_value_len) | |
2d7da676 UD |
43 | |
44 | static enum nss_status | |
d71b808a | 45 | _nss_create_tablename (int *errnop) |
2d7da676 UD |
46 | { |
47 | if (tablename_val == NULL) | |
48 | { | |
636e689e UD |
49 | const char *local_dir = nis_local_directory (); |
50 | size_t local_dir_len = strlen (local_dir); | |
51 | static const char prefix[] = "mail_aliases.org_dir."; | |
2d7da676 | 52 | |
636e689e | 53 | char *p = malloc (sizeof (prefix) + local_dir_len); |
c8e82b4a | 54 | if (p == NULL) |
d71b808a UD |
55 | { |
56 | *errnop = errno; | |
57 | return NSS_STATUS_TRYAGAIN; | |
58 | } | |
636e689e UD |
59 | |
60 | memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1); | |
61 | ||
62 | tablename_len = sizeof (prefix) - 1 + local_dir_len; | |
63 | ||
64 | atomic_write_barrier (); | |
65 | ||
66 | tablename_val = p; | |
2d7da676 | 67 | } |
636e689e | 68 | |
2d7da676 UD |
69 | return NSS_STATUS_SUCCESS; |
70 | } | |
e61abf83 UD |
71 | |
72 | static int | |
2d7da676 UD |
73 | _nss_nisplus_parse_aliasent (nis_result *result, unsigned long entry, |
74 | struct aliasent *alias, char *buffer, | |
d71b808a | 75 | size_t buflen, int *errnop) |
e61abf83 UD |
76 | { |
77 | if (result == NULL) | |
26dee9c4 | 78 | return 0; |
e61abf83 | 79 | |
d71b808a | 80 | if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) |
3fc044a1 UD |
81 | || __type_of (&NIS_RES_OBJECT (result)[entry]) != NIS_ENTRY_OBJ |
82 | || strcmp (NIS_RES_OBJECT (result)[entry].EN_data.en_type, | |
d71b808a | 83 | "mail_aliases") != 0 |
3fc044a1 | 84 | || NIS_RES_OBJECT (result)[entry].EN_data.en_cols.en_cols_len < 2) |
26dee9c4 | 85 | return 0; |
636e689e | 86 | |
636e689e | 87 | if (NISENTRYLEN (entry, 1, result) >= buflen) |
0ecb606c | 88 | { |
636e689e UD |
89 | /* The line is too long for our buffer. */ |
90 | no_more_room: | |
91 | *errnop = ERANGE; | |
92 | return -1; | |
93 | } | |
94 | ||
95 | char *cp = __stpncpy (buffer, NISENTRYVAL (entry, 1, result), | |
96 | NISENTRYLEN (entry, 1, result)); | |
97 | *cp = '\0'; | |
98 | ||
3fc044a1 UD |
99 | char *first_unused = cp + 1; |
100 | size_t room_left = buflen - (first_unused - buffer); | |
636e689e UD |
101 | |
102 | alias->alias_local = 0; | |
103 | alias->alias_members_len = 0; | |
3fc044a1 UD |
104 | |
105 | if (NISENTRYLEN (entry, 0, result) >= room_left) | |
106 | goto no_more_room; | |
107 | ||
636e689e UD |
108 | cp = __stpncpy (first_unused, NISENTRYVAL (entry, 0, result), |
109 | NISENTRYLEN (entry, 0, result)); | |
110 | *cp = '\0'; | |
111 | alias->alias_name = first_unused; | |
112 | ||
113 | /* Terminate the line for any case. */ | |
114 | cp = strpbrk (alias->alias_name, "#\n"); | |
115 | if (cp != NULL) | |
116 | *cp = '\0'; | |
117 | ||
3fc044a1 UD |
118 | size_t len = strlen (alias->alias_name) + 1; |
119 | first_unused += len; | |
120 | room_left -= len; | |
121 | ||
636e689e UD |
122 | /* Adjust the pointer so it is aligned for |
123 | storing pointers. */ | |
3fc044a1 UD |
124 | size_t adjust = ((__alignof__ (char *) |
125 | - (first_unused - (char *) 0) % __alignof__ (char *)) | |
126 | % __alignof__ (char *)); | |
127 | if (room_left < adjust) | |
128 | goto no_more_room; | |
129 | first_unused += adjust; | |
130 | room_left -= adjust; | |
131 | ||
636e689e UD |
132 | alias->alias_members = (char **) first_unused; |
133 | ||
134 | char *line = buffer; | |
135 | while (*line != '\0') | |
136 | { | |
137 | /* Skip leading blanks. */ | |
138 | while (isspace (*line)) | |
139 | ++line; | |
140 | ||
141 | if (*line == '\0') | |
142 | break; | |
0ecb606c | 143 | |
636e689e | 144 | if (room_left < sizeof (char *)) |
e61abf83 | 145 | goto no_more_room; |
636e689e UD |
146 | room_left -= sizeof (char *); |
147 | alias->alias_members[alias->alias_members_len] = line; | |
148 | ||
149 | while (*line != '\0' && *line != ',') | |
150 | ++line; | |
e61abf83 | 151 | |
636e689e | 152 | if (line != alias->alias_members[alias->alias_members_len]) |
e61abf83 | 153 | { |
636e689e | 154 | *line++ = '\0'; |
3fc044a1 | 155 | ++alias->alias_members_len; |
e61abf83 | 156 | } |
3fc044a1 UD |
157 | else if (*line == ',') |
158 | ++line; | |
a334319f | 159 | } |
636e689e UD |
160 | |
161 | return alias->alias_members_len == 0 ? 0 : 1; | |
e61abf83 UD |
162 | } |
163 | ||
2d7da676 UD |
164 | static enum nss_status |
165 | internal_setaliasent (void) | |
e61abf83 | 166 | { |
8f2ece69 | 167 | enum nss_status status; |
d71b808a | 168 | int err; |
8f2ece69 | 169 | |
636e689e UD |
170 | if (result != NULL) |
171 | { | |
172 | nis_freeresult (result); | |
173 | result = NULL; | |
174 | } | |
2d7da676 | 175 | |
d71b808a | 176 | if (_nss_create_tablename (&err) != NSS_STATUS_SUCCESS) |
2d7da676 UD |
177 | return NSS_STATUS_UNAVAIL; |
178 | ||
179 | next_entry = 0; | |
d71b808a | 180 | result = nis_list (tablename_val, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); |
901956a5 | 181 | if (result == NULL) |
e61abf83 | 182 | { |
901956a5 UD |
183 | status = NSS_STATUS_TRYAGAIN; |
184 | __set_errno (ENOMEM); | |
185 | } | |
186 | else | |
187 | { | |
188 | status = niserr2nss (result->status); | |
189 | if (status != NSS_STATUS_SUCCESS) | |
190 | { | |
191 | nis_freeresult (result); | |
192 | result = NULL; | |
193 | } | |
e61abf83 | 194 | } |
8f2ece69 | 195 | return status; |
2d7da676 UD |
196 | } |
197 | ||
198 | enum nss_status | |
199 | _nss_nisplus_setaliasent (void) | |
200 | { | |
201 | enum nss_status status; | |
202 | ||
203 | __libc_lock_lock (lock); | |
204 | ||
205 | status = internal_setaliasent (); | |
e61abf83 UD |
206 | |
207 | __libc_lock_unlock (lock); | |
208 | ||
2d7da676 | 209 | return status; |
e61abf83 UD |
210 | } |
211 | ||
212 | enum nss_status | |
213 | _nss_nisplus_endaliasent (void) | |
214 | { | |
215 | __libc_lock_lock (lock); | |
216 | ||
636e689e UD |
217 | if (result != NULL) |
218 | { | |
219 | nis_freeresult (result); | |
220 | result = NULL; | |
221 | } | |
2d7da676 | 222 | next_entry = 0; |
e61abf83 UD |
223 | |
224 | __libc_lock_unlock (lock); | |
225 | ||
226 | return NSS_STATUS_SUCCESS; | |
227 | } | |
228 | ||
229 | static enum nss_status | |
230 | internal_nisplus_getaliasent_r (struct aliasent *alias, | |
d71b808a | 231 | char *buffer, size_t buflen, int *errnop) |
e61abf83 UD |
232 | { |
233 | int parse_res; | |
234 | ||
2d7da676 | 235 | if (result == NULL) |
8f2ece69 UD |
236 | { |
237 | enum nss_status status; | |
238 | ||
239 | status = internal_setaliasent (); | |
240 | if (result == NULL || status != NSS_STATUS_SUCCESS) | |
241 | return status; | |
242 | } | |
2d7da676 | 243 | |
e61abf83 UD |
244 | /* Get the next entry until we found a correct one. */ |
245 | do | |
246 | { | |
2d7da676 UD |
247 | if (next_entry >= result->objects.objects_len) |
248 | return NSS_STATUS_NOTFOUND; | |
e61abf83 | 249 | |
d71b808a UD |
250 | parse_res = _nss_nisplus_parse_aliasent (result, next_entry, alias, |
251 | buffer, buflen, errnop); | |
252 | if (parse_res == -1) | |
60c96635 UD |
253 | return NSS_STATUS_TRYAGAIN; |
254 | ||
2d7da676 | 255 | ++next_entry; |
636e689e UD |
256 | } |
257 | while (!parse_res); | |
e61abf83 UD |
258 | |
259 | return NSS_STATUS_SUCCESS; | |
260 | } | |
261 | ||
262 | enum nss_status | |
263 | _nss_nisplus_getaliasent_r (struct aliasent *result, char *buffer, | |
d71b808a | 264 | size_t buflen, int *errnop) |
e61abf83 UD |
265 | { |
266 | int status; | |
267 | ||
268 | __libc_lock_lock (lock); | |
269 | ||
d71b808a | 270 | status = internal_nisplus_getaliasent_r (result, buffer, buflen, errnop); |
e61abf83 UD |
271 | |
272 | __libc_lock_unlock (lock); | |
273 | ||
274 | return status; | |
275 | } | |
276 | ||
277 | enum nss_status | |
278 | _nss_nisplus_getaliasbyname_r (const char *name, struct aliasent *alias, | |
d71b808a | 279 | char *buffer, size_t buflen, int *errnop) |
e61abf83 UD |
280 | { |
281 | int parse_res; | |
282 | ||
2d7da676 | 283 | if (tablename_val == NULL) |
d71b808a | 284 | { |
636e689e UD |
285 | __libc_lock_lock (lock); |
286 | ||
d71b808a | 287 | enum nss_status status = _nss_create_tablename (errnop); |
636e689e UD |
288 | |
289 | __libc_lock_unlock (lock); | |
290 | ||
d71b808a UD |
291 | if (status != NSS_STATUS_SUCCESS) |
292 | return status; | |
293 | } | |
2d7da676 | 294 | |
ac9f45cf UD |
295 | if (name != NULL) |
296 | { | |
297 | *errnop = EINVAL; | |
298 | return NSS_STATUS_UNAVAIL; | |
299 | } | |
e61abf83 | 300 | |
636e689e UD |
301 | char buf[strlen (name) + 9 + tablename_len]; |
302 | int olderr = errno; | |
e61abf83 | 303 | |
636e689e | 304 | snprintf (buf, sizeof (buf), "[name=%s],%s", name, tablename_val); |
e61abf83 | 305 | |
636e689e | 306 | nis_result *result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL); |
e61abf83 | 307 | |
636e689e UD |
308 | if (result == NULL) |
309 | { | |
310 | *errnop = ENOMEM; | |
311 | return NSS_STATUS_TRYAGAIN; | |
312 | } | |
34816665 | 313 | |
636e689e | 314 | if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0)) |
0292b0dd UD |
315 | { |
316 | enum nss_status status = niserr2nss (result->status); | |
317 | nis_freeresult (result); | |
318 | return status; | |
319 | } | |
636e689e UD |
320 | |
321 | parse_res = _nss_nisplus_parse_aliasent (result, 0, alias, | |
322 | buffer, buflen, errnop); | |
0292b0dd UD |
323 | |
324 | /* We do not need the lookup result anymore. */ | |
325 | nis_freeresult (result); | |
326 | ||
636e689e UD |
327 | if (__builtin_expect (parse_res < 1, 0)) |
328 | { | |
329 | __set_errno (olderr); | |
330 | ||
331 | if (parse_res == -1) | |
332 | return NSS_STATUS_TRYAGAIN; | |
333 | else | |
334 | return NSS_STATUS_NOTFOUND; | |
e61abf83 | 335 | } |
636e689e UD |
336 | |
337 | return NSS_STATUS_SUCCESS; | |
e61abf83 | 338 | } |