]> git.ipfire.org Git - thirdparty/glibc.git/blob - nis/nss_nisplus/nisplus-rpc.c
e35d846ed38063bf62992dcee3fc1e9c6e1e67be
[thirdparty/glibc.git] / nis / nss_nisplus / nisplus-rpc.c
1 /* Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20 #include <nss.h>
21 #include <errno.h>
22 #include <ctype.h>
23 #include <string.h>
24 #include <bits/libc-lock.h>
25 #include <rpc/netdb.h>
26 #include <rpcsvc/nis.h>
27
28 #include "nss-nisplus.h"
29
30 __libc_lock_define_initialized (static, lock)
31
32 static nis_result *result;
33 static nis_name tablename_val;
34 static u_long tablename_len;
35
36 #define NISENTRYVAL(idx,col,res) \
37 ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
38
39 #define NISENTRYLEN(idx,col,res) \
40 ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
41
42 static int
43 _nss_nisplus_parse_rpcent (nis_result *result, struct rpcent *rpc,
44 char *buffer, size_t buflen, int *errnop)
45 {
46 char *first_unused = buffer;
47 size_t room_left = buflen;
48 unsigned int i;
49 char *p, *line;
50
51
52 if (result == NULL)
53 return 0;
54
55 if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
56 || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
57 || strcmp (result->objects.objects_val[0].EN_data.en_type,
58 "rpc_tbl") != 0
59 || result->objects.objects_val[0].EN_data.en_cols.en_cols_len < 3)
60 return 0;
61
62 if (NISENTRYLEN (0, 0, result) >= room_left)
63 {
64 no_more_room:
65 *errnop = ERANGE;
66 return -1;
67 }
68 strncpy (first_unused, NISENTRYVAL (0, 0, result),
69 NISENTRYLEN (0, 0, result));
70 first_unused[NISENTRYLEN (0, 0, result)] = '\0';
71 rpc->r_name = first_unused;
72 room_left -= (strlen (first_unused) + 1);
73 first_unused += strlen (first_unused) + 1;
74 rpc->r_number = atoi (NISENTRYVAL (0, 2, result));
75 p = first_unused;
76
77 line = p;
78 for (i = 0; i < result->objects.objects_len; ++i)
79 {
80 if (strcmp (NISENTRYVAL (i, 1, result), rpc->r_name) != 0)
81 {
82 if (NISENTRYLEN (i, 1, result) + 2 > room_left)
83 goto no_more_room;
84 *p++ = ' ';
85 p = __stpncpy (p, NISENTRYVAL (i, 1, result),
86 NISENTRYLEN (i, 1, result));
87 *p = '\0';
88 room_left -= (NISENTRYLEN (i, 1, result) + 1);
89 }
90 }
91 ++p;
92 first_unused = p;
93
94 /* Adjust the pointer so it is aligned for
95 storing pointers. */
96 first_unused += __alignof__ (char *) - 1;
97 first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
98 rpc->r_aliases = (char **) first_unused;
99 if (room_left < sizeof (char *))
100 goto no_more_room;
101 room_left -= sizeof (char *);
102 rpc->r_aliases[0] = NULL;
103
104 i = 0;
105 while (*line != '\0')
106 {
107 /* Skip leading blanks. */
108 while (isspace (*line))
109 ++line;
110
111 if (*line == '\0')
112 break;
113
114 if (room_left < sizeof (char *))
115 goto no_more_room;
116
117 room_left -= sizeof (char *);
118 rpc->r_aliases[i] = line;
119
120 while (*line != '\0' && *line != ' ')
121 ++line;
122
123 if (*line == ' ')
124 {
125 *line = '\0';
126 ++line;
127 ++i;
128 }
129 else
130 rpc->r_aliases[i+1] = NULL;
131 }
132
133 return 1;
134 }
135
136 static enum nss_status
137 _nss_create_tablename (int *errnop)
138 {
139 if (tablename_val == NULL)
140 {
141 char buf [40 + strlen (nis_local_directory ())];
142 char *p;
143
144 p = __stpcpy (buf, "rpc.org_dir.");
145 p = __stpcpy (p, nis_local_directory ());
146 tablename_val = __strdup (buf);
147 if (tablename_val == NULL)
148 {
149 *errnop = errno;
150 return NSS_STATUS_TRYAGAIN;
151 }
152 tablename_len = strlen (tablename_val);
153 }
154 return NSS_STATUS_SUCCESS;
155 }
156
157
158 enum nss_status
159 _nss_nisplus_setrpcent (int stayopen)
160 {
161 enum nss_status status = NSS_STATUS_SUCCESS;
162 int err;
163
164 __libc_lock_lock (lock);
165
166 if (result)
167 nis_freeresult (result);
168 result = NULL;
169
170 if (tablename_val == NULL)
171 status = _nss_create_tablename (&err);
172
173 __libc_lock_unlock (lock);
174
175 return status;
176 }
177
178 enum nss_status
179 _nss_nisplus_endrpcent (void)
180 {
181 __libc_lock_lock (lock);
182
183 if (result)
184 nis_freeresult (result);
185 result = NULL;
186
187 __libc_lock_unlock (lock);
188
189 return NSS_STATUS_SUCCESS;
190 }
191
192 static enum nss_status
193 internal_nisplus_getrpcent_r (struct rpcent *rpc, char *buffer,
194 size_t buflen, int *errnop)
195 {
196 int parse_res;
197
198 /* Get the next entry until we found a correct one. */
199 do
200 {
201 nis_result *saved_res;
202
203 if (result == NULL)
204 {
205 saved_res = NULL;
206 if (tablename_val == NULL)
207 {
208 enum nss_status status = _nss_create_tablename (errnop);
209
210 if (status != NSS_STATUS_SUCCESS)
211 return status;
212 }
213
214 result = nis_first_entry (tablename_val);
215 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
216 return niserr2nss (result->status);
217 }
218 else
219 {
220 nis_result *res;
221
222 saved_res = result;
223 res = nis_next_entry (tablename_val, &result->cookie);
224 result = res;
225 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
226 {
227 nis_freeresult (saved_res);
228 return niserr2nss (result->status);
229 }
230 }
231
232 parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer,
233 buflen, errnop);
234 if (parse_res == -1)
235 {
236 nis_freeresult (result);
237 result = saved_res;
238 *errnop = ERANGE;
239 return NSS_STATUS_TRYAGAIN;
240 }
241 else
242 {
243 if (saved_res)
244 nis_freeresult (saved_res);
245 }
246 } while (!parse_res);
247
248 return NSS_STATUS_SUCCESS;
249 }
250
251 enum nss_status
252 _nss_nisplus_getrpcent_r (struct rpcent *result, char *buffer,
253 size_t buflen, int *errnop)
254 {
255 int status;
256
257 __libc_lock_lock (lock);
258
259 status = internal_nisplus_getrpcent_r (result, buffer, buflen, errnop);
260
261 __libc_lock_unlock (lock);
262
263 return status;
264 }
265
266 enum nss_status
267 _nss_nisplus_getrpcbyname_r (const char *name, struct rpcent *rpc,
268 char *buffer, size_t buflen, int *errnop)
269 {
270 int parse_res;
271
272 if (tablename_val == NULL)
273 {
274 enum nss_status status = _nss_create_tablename (errnop);
275
276 if (status != NSS_STATUS_SUCCESS)
277 return status;
278 }
279
280 if (name == NULL)
281 return NSS_STATUS_NOTFOUND;
282 else
283 {
284 nis_result *result;
285 char buf[strlen (name) + 255 + tablename_len];
286
287 /* Search at first in the alias list, and use the correct name
288 for the next search */
289 sprintf (buf, "[name=%s],%s", name, tablename_val);
290 result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
291
292 /* If we do not find it, try it as original name. But if the
293 database is correct, we should find it in the first case, too */
294 if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS)
295 || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
296 || strcmp (result->objects.objects_val->EN_data.en_type,
297 "rpc_tbl") != 0
298 || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
299 sprintf (buf, "[cname=%s],%s", name, tablename_val);
300 else
301 sprintf (buf, "[cname=%s],%s", NISENTRYVAL (0, 0, result),
302 tablename_val);
303
304 nis_freeresult (result);
305 result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS , NULL, NULL);
306
307 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
308 {
309 enum nss_status status = niserr2nss (result->status);
310
311 nis_freeresult (result);
312 return status;
313 }
314
315 parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen,
316 errnop);
317
318 nis_freeresult (result);
319
320 if (parse_res < 1)
321 {
322 if (parse_res == -1)
323 {
324 *errnop = ERANGE;
325 return NSS_STATUS_TRYAGAIN;
326 }
327 return NSS_STATUS_NOTFOUND;
328 }
329 return NSS_STATUS_SUCCESS;
330 }
331 }
332
333 enum nss_status
334 _nss_nisplus_getrpcbynumber_r (const int number, struct rpcent *rpc,
335 char *buffer, size_t buflen, int *errnop)
336 {
337 if (tablename_val == NULL)
338 {
339 enum nss_status status = _nss_create_tablename (errnop);
340
341 if (status != NSS_STATUS_SUCCESS)
342 return status;
343 }
344
345 {
346 int parse_res;
347 nis_result *result;
348 char buf[100 + tablename_len];
349
350 sprintf (buf, "[number=%d],%s", number, tablename_val);
351
352 result = nis_list(buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
353
354 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
355 {
356 enum nss_status status = niserr2nss (result->status);
357
358 nis_freeresult (result);
359 return status;
360 }
361
362 parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen,
363 errnop);
364
365 nis_freeresult (result);
366
367 if (parse_res < 1)
368 {
369 if (parse_res == -1)
370 {
371 *errnop = ERANGE;
372 return NSS_STATUS_TRYAGAIN;
373 }
374 else
375 return NSS_STATUS_NOTFOUND;
376 }
377 return NSS_STATUS_SUCCESS;
378 }
379 }