(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / nis / nss_nisplus / nisplus-rpc.c
blob31d48d17a37260666e30ae2fb4df10c1008df0a2
1 /* Copyright (C) 1997, 1998, 2001, 2002, 2003 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.
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.
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.
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. */
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>
28 #include "nss-nisplus.h"
30 __libc_lock_define_initialized (static, lock)
32 static nis_result *result;
33 static nis_name tablename_val;
34 static u_long tablename_len;
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)
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)
42 static int
43 _nss_nisplus_parse_rpcent (nis_result *result, struct rpcent *rpc,
44 char *buffer, size_t buflen, int *errnop)
46 char *first_unused = buffer;
47 size_t room_left = buflen;
48 unsigned int i;
49 char *p, *line;
52 if (result == NULL)
53 return 0;
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;
62 if (NISENTRYLEN (0, 0, result) >= room_left)
64 no_more_room:
65 *errnop = ERANGE;
66 return -1;
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;
77 line = p;
78 for (i = 0; i < result->objects.objects_len; ++i)
80 if (strcmp (NISENTRYVAL (i, 1, result), rpc->r_name) != 0)
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);
91 ++p;
92 first_unused = p;
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;
104 i = 0;
105 while (*line != '\0')
107 /* Skip leading blanks. */
108 while (isspace (*line))
109 ++line;
111 if (*line == '\0')
112 break;
114 if (room_left < sizeof (char *))
115 goto no_more_room;
117 room_left -= sizeof (char *);
118 rpc->r_aliases[i] = line;
120 while (*line != '\0' && *line != ' ')
121 ++line;
123 if (*line == ' ')
125 *line = '\0';
126 ++line;
127 ++i;
129 else
130 rpc->r_aliases[i+1] = NULL;
133 return 1;
136 static enum nss_status
137 _nss_create_tablename (int *errnop)
139 if (tablename_val == NULL)
141 char buf [40 + strlen (nis_local_directory ())];
142 char *p;
144 p = __stpcpy (buf, "rpc.org_dir.");
145 p = __stpcpy (p, nis_local_directory ());
146 tablename_val = __strdup (buf);
147 if (tablename_val == NULL)
149 *errnop = errno;
150 return NSS_STATUS_TRYAGAIN;
152 tablename_len = strlen (tablename_val);
154 return NSS_STATUS_SUCCESS;
158 enum nss_status
159 _nss_nisplus_setrpcent (int stayopen)
161 enum nss_status status = NSS_STATUS_SUCCESS;
162 int err;
164 __libc_lock_lock (lock);
166 if (result)
167 nis_freeresult (result);
168 result = NULL;
170 if (tablename_val == NULL)
171 status = _nss_create_tablename (&err);
173 __libc_lock_unlock (lock);
175 return status;
178 enum nss_status
179 _nss_nisplus_endrpcent (void)
181 __libc_lock_lock (lock);
183 if (result)
184 nis_freeresult (result);
185 result = NULL;
187 __libc_lock_unlock (lock);
189 return NSS_STATUS_SUCCESS;
192 static enum nss_status
193 internal_nisplus_getrpcent_r (struct rpcent *rpc, char *buffer,
194 size_t buflen, int *errnop)
196 int parse_res;
198 /* Get the next entry until we found a correct one. */
201 nis_result *saved_res;
203 if (result == NULL)
205 saved_res = NULL;
206 if (tablename_val == NULL)
208 enum nss_status status = _nss_create_tablename (errnop);
210 if (status != NSS_STATUS_SUCCESS)
211 return status;
214 result = nis_first_entry (tablename_val);
215 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
216 return niserr2nss (result->status);
218 else
220 nis_result *res;
222 saved_res = result;
223 res = nis_next_entry (tablename_val, &result->cookie);
224 result = res;
225 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
227 nis_freeresult (saved_res);
228 return niserr2nss (result->status);
232 parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer,
233 buflen, errnop);
234 if (parse_res == -1)
236 nis_freeresult (result);
237 result = saved_res;
238 *errnop = ERANGE;
239 return NSS_STATUS_TRYAGAIN;
241 else
243 if (saved_res)
244 nis_freeresult (saved_res);
246 } while (!parse_res);
248 return NSS_STATUS_SUCCESS;
251 enum nss_status
252 _nss_nisplus_getrpcent_r (struct rpcent *result, char *buffer,
253 size_t buflen, int *errnop)
255 int status;
257 __libc_lock_lock (lock);
259 status = internal_nisplus_getrpcent_r (result, buffer, buflen, errnop);
261 __libc_lock_unlock (lock);
263 return status;
266 enum nss_status
267 _nss_nisplus_getrpcbyname_r (const char *name, struct rpcent *rpc,
268 char *buffer, size_t buflen, int *errnop)
270 int parse_res;
272 if (tablename_val == NULL)
274 enum nss_status status = _nss_create_tablename (errnop);
276 if (status != NSS_STATUS_SUCCESS)
277 return status;
280 if (name == NULL)
281 return NSS_STATUS_NOTFOUND;
282 else
284 nis_result *result;
285 char buf[strlen (name) + 255 + tablename_len];
286 int olderr = errno;
288 /* Search at first in the alias list, and use the correct name
289 for the next search */
290 sprintf (buf, "[name=%s],%s", name, tablename_val);
291 result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
293 if (result != NULL)
295 /* If we do not find it, try it as original name. But if the
296 database is correct, we should find it in the first case, too */
297 if ((result->status != NIS_SUCCESS
298 && result->status != NIS_S_SUCCESS)
299 || __type_of (result->objects.objects_val) != NIS_ENTRY_OBJ
300 || strcmp (result->objects.objects_val->EN_data.en_type,
301 "rpc_tbl") != 0
302 || result->objects.objects_val->EN_data.en_cols.en_cols_len < 3)
303 sprintf (buf, "[cname=%s],%s", name, tablename_val);
304 else
305 sprintf (buf, "[cname=%s],%s", NISENTRYVAL (0, 0, result),
306 tablename_val);
308 nis_freeresult (result);
309 result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS , NULL, NULL);
312 if (result == NULL)
314 *errnop = ENOMEM;
315 return NSS_STATUS_TRYAGAIN;
317 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
319 enum nss_status status = niserr2nss (result->status);
321 __set_errno (olderr);
323 nis_freeresult (result);
324 return status;
327 parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen,
328 errnop);
330 nis_freeresult (result);
332 if (parse_res < 1)
334 if (parse_res == -1)
336 *errnop = ERANGE;
337 return NSS_STATUS_TRYAGAIN;
340 __set_errno (olderr);
341 return NSS_STATUS_NOTFOUND;
343 return NSS_STATUS_SUCCESS;
347 enum nss_status
348 _nss_nisplus_getrpcbynumber_r (const int number, struct rpcent *rpc,
349 char *buffer, size_t buflen, int *errnop)
351 if (tablename_val == NULL)
353 enum nss_status status = _nss_create_tablename (errnop);
355 if (status != NSS_STATUS_SUCCESS)
356 return status;
360 int parse_res;
361 nis_result *result;
362 char buf[100 + tablename_len];
363 int olderr = errno;
365 sprintf (buf, "[number=%d],%s", number, tablename_val);
367 result = nis_list(buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
369 if (result == NULL)
371 *errnop = ENOMEM;
372 return NSS_STATUS_TRYAGAIN;
374 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
376 enum nss_status status = niserr2nss (result->status);
378 __set_errno (olderr);
380 nis_freeresult (result);
381 return status;
384 parse_res = _nss_nisplus_parse_rpcent (result, rpc, buffer, buflen,
385 errnop);
387 nis_freeresult (result);
389 if (parse_res < 1)
391 if (parse_res == -1)
393 *errnop = ERANGE;
394 return NSS_STATUS_TRYAGAIN;
396 else
398 __set_errno (olderr);
399 return NSS_STATUS_NOTFOUND;
402 return NSS_STATUS_SUCCESS;