Updated to fedora-glibc-20051116T0829
[glibc.git] / nis / nis_table.c
blob2531a3fbc59f69578272634cbae11ddab38019c9
1 /* Copyright (c) 1997,1998,1999,2003,2004,2005 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.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 <string.h>
21 #include <rpcsvc/nis.h>
23 #include "nis_xdr.h"
24 #include "nis_intern.h"
27 static struct ib_request *
28 __create_ib_request (const_nis_name name, unsigned int flags)
30 struct ib_request *ibreq = calloc (1, sizeof (ib_request));
31 char buf[strlen (name) + 1];
32 nis_attr *search_val = NULL;
33 size_t search_len = 0;
34 char *cptr;
35 size_t size = 0;
37 if (ibreq == NULL)
38 return NULL;
40 ibreq->ibr_flags = flags;
42 cptr = strcpy (buf, name);
44 /* Not of "[key=value,key=value,...],foo.." format? */
45 if (cptr[0] != '[')
46 return (ibreq->ibr_name = strdup (cptr)) == NULL ? NULL : ibreq;
48 /* "[key=value,...],foo" format */
49 ibreq->ibr_name = strchr (cptr, ']');
50 if (ibreq->ibr_name == NULL || ibreq->ibr_name[1] != ',')
52 ibreq->ibr_name = NULL; /* Or the xdr_* functions will dump */
53 nis_free_request (ibreq);
54 return NULL;
57 /* Check if we have an entry of "[key=value,],bar". If, remove the "," */
58 if (ibreq->ibr_name[-1] == ',')
59 ibreq->ibr_name[-1] = '\0';
60 else
61 ibreq->ibr_name[0] = '\0';
62 ibreq->ibr_name += 2;
63 ibreq->ibr_name = strdup (ibreq->ibr_name);
64 if (ibreq->ibr_name == NULL)
66 free_null:
67 while (search_len-- > 0)
69 free (search_val[search_len].zattr_ndx);
70 free (search_val[search_len].zattr_val.zattr_val_val);
72 free (search_val);
73 nis_free_request (ibreq);
74 return NULL;
77 ++cptr; /* Remove "[" */
79 while (cptr != NULL && cptr[0] != '\0')
81 char *key = cptr;
82 char *val = strchr (cptr, '=');
84 cptr = strchr (key, ',');
85 if (cptr != NULL)
86 *cptr++ = '\0';
88 if (!val)
90 nis_free_request (ibreq);
91 return NULL;
93 *val++ = '\0';
94 if ((search_len + 1) >= size)
96 size += 1;
97 nis_attr *newp = realloc (search_val, size * sizeof (nis_attr));
98 if (newp == NULL)
99 goto free_null;
100 search_val = newp;
102 search_val[search_len].zattr_ndx = strdup (key);
103 if ((search_val[search_len].zattr_ndx) == NULL)
104 goto free_null;
106 search_val[search_len].zattr_val.zattr_val_len = strlen (val) + 1;
107 search_val[search_len].zattr_val.zattr_val_val = strdup (val);
108 if (search_val[search_len].zattr_val.zattr_val_val == NULL)
110 free (search_val[search_len].zattr_ndx);
111 goto free_null;
114 ++search_len;
117 ibreq->ibr_srch.ibr_srch_val = search_val;
118 ibreq->ibr_srch.ibr_srch_len = search_len;
120 return ibreq;
123 static struct timeval RPCTIMEOUT = {10, 0};
125 static char *
126 __get_tablepath (char *name, dir_binding *bptr)
128 enum clnt_stat result;
129 nis_result *res = calloc (1, sizeof (nis_result));
130 struct ns_request req;
132 if (res == NULL)
133 return NULL;
135 req.ns_name = name;
136 req.ns_object.ns_object_len = 0;
137 req.ns_object.ns_object_val = NULL;
139 result = clnt_call (bptr->clnt, NIS_LOOKUP, (xdrproc_t) _xdr_ns_request,
140 (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
141 (caddr_t) res, RPCTIMEOUT);
143 if (result == RPC_SUCCESS && NIS_RES_STATUS (res) == NIS_SUCCESS &&
144 __type_of (NIS_RES_OBJECT (res)) == NIS_TABLE_OBJ)
146 char *cptr = strdup (NIS_RES_OBJECT (res)->TA_data.ta_path);
147 nis_freeresult (res);
148 return cptr;
150 else
152 nis_freeresult (res);
153 return strdup ("");
157 nis_result *
158 nis_list (const_nis_name name, unsigned int flags,
159 int (*callback) (const_nis_name name,
160 const nis_object *object,
161 const void *userdata),
162 const void *userdata)
164 nis_result *res = calloc (1, sizeof (nis_result));
165 ib_request *ibreq;
166 int status;
167 enum clnt_stat clnt_status;
168 int count_links = 0; /* We will only follow NIS_MAXLINKS links! */
169 int done = 0;
170 nis_name *names;
171 nis_name namebuf[2] = {NULL, NULL};
172 int name_nr = 0;
173 nis_cb *cb = NULL;
174 char *tableptr, *tablepath = NULL;
175 int have_tablepath = 0;
176 int first_try = 0; /* Do we try the old binding at first ? */
178 if (res == NULL)
179 return NULL;
181 if (name == NULL)
183 NIS_RES_STATUS (res) = NIS_BADNAME;
184 return res;
187 if ((ibreq = __create_ib_request (name, flags)) == NULL)
189 NIS_RES_STATUS (res) = NIS_BADNAME;
190 return res;
193 if ((flags & EXPAND_NAME)
194 && ibreq->ibr_name[strlen (ibreq->ibr_name) - 1] != '.')
196 names = nis_getnames (ibreq->ibr_name);
197 free (ibreq->ibr_name);
198 ibreq->ibr_name = NULL;
199 if (names == NULL)
201 nis_free_request (ibreq);
202 NIS_RES_STATUS (res) = NIS_BADNAME;
203 return res;
205 ibreq->ibr_name = strdup (names[name_nr]);
206 if (ibreq->ibr_name == NULL)
208 nis_free_request (ibreq);
209 NIS_RES_STATUS (res) = NIS_NOMEMORY;
210 return res;
213 else
215 names = namebuf;
216 names[name_nr] = ibreq->ibr_name;
219 cb = NULL;
221 while (!done)
223 dir_binding bptr;
224 directory_obj *dir = NULL;
226 memset (res, '\0', sizeof (nis_result));
228 status = __nisfind_server (ibreq->ibr_name, &dir);
229 if (status != NIS_SUCCESS)
231 nis_free_request (ibreq);
232 NIS_RES_STATUS (res) = status;
233 return res;
236 status = __nisbind_create (&bptr, dir->do_servers.do_servers_val,
237 dir->do_servers.do_servers_len, flags);
238 if (status != NIS_SUCCESS)
240 nis_free_request (ibreq);
241 NIS_RES_STATUS (res) = status;
242 nis_free_directory (dir);
243 return res;
246 while (__nisbind_connect (&bptr) != NIS_SUCCESS)
247 if (__nisbind_next (&bptr) != NIS_SUCCESS)
249 __nisbind_destroy (&bptr);
250 nis_free_directory (dir);
251 nis_free_request (ibreq);
252 NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
253 return res;
256 if (callback != NULL)
258 cb = __nis_create_callback (callback, userdata, flags);
259 ibreq->ibr_cbhost.ibr_cbhost_len = 1;
260 ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv;
263 again:
264 clnt_status = clnt_call (bptr.clnt, NIS_IBLIST,
265 (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq,
266 (xdrproc_t) _xdr_nis_result,
267 (caddr_t) res, RPCTIMEOUT);
269 if (clnt_status != RPC_SUCCESS)
270 NIS_RES_STATUS (res) = NIS_RPCERROR;
271 else
272 switch (NIS_RES_STATUS (res))
273 { /* start switch */
274 case NIS_PARTIAL:
275 case NIS_SUCCESS:
276 case NIS_S_SUCCESS:
277 if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ &&
278 flags & FOLLOW_LINKS) /* We are following links. */
280 free (ibreq->ibr_name);
281 ibreq->ibr_name = NULL;
282 /* If we hit the link limit, bail. */
283 if (count_links > NIS_MAXLINKS)
285 NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
286 ++done;
287 break;
289 ++count_links;
290 ibreq->ibr_name =
291 strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
292 if (ibreq->ibr_name == NULL)
294 nis_free_request (ibreq);
295 NIS_RES_STATUS (res) = NIS_NOMEMORY;
296 return res;
298 if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
299 if (ibreq->ibr_srch.ibr_srch_len == 0)
301 ibreq->ibr_srch.ibr_srch_len =
302 NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len;
303 ibreq->ibr_srch.ibr_srch_val =
304 NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
306 nis_freeresult (res);
307 res = calloc (1, sizeof (nis_result));
308 if (res == NULL)
310 if (have_tablepath)
311 free (tablepath);
312 __nisbind_destroy (&bptr);
313 nis_free_directory (dir);
314 return NULL;
316 first_try = 1; /* Try at first the old binding */
317 goto again;
319 else if ((flags & FOLLOW_PATH) &&
320 NIS_RES_STATUS (res) == NIS_PARTIAL)
322 if (!have_tablepath)
324 tablepath = __get_tablepath (ibreq->ibr_name, &bptr);
325 tableptr = tablepath;
326 have_tablepath = 1;
328 if (tableptr == NULL)
330 ++done;
331 break;
333 free (ibreq->ibr_name);
334 ibreq->ibr_name = strsep (&tableptr, ":");
335 if (ibreq->ibr_name == NULL || ibreq->ibr_name[0] == '\0')
337 ibreq->ibr_name = strdup ("");
338 if (ibreq->ibr_name == NULL)
340 nis_free_request (ibreq);
341 NIS_RES_STATUS (res) = NIS_NOMEMORY;
342 return res;
344 ++done;
346 else
348 ibreq->ibr_name = strdup (ibreq->ibr_name);
349 nis_freeresult (res);
350 res = calloc (1, sizeof (nis_result));
351 if (res == NULL || ibreq->ibr_name == NULL)
353 free (res);
354 nis_free_request (ibreq);
355 if (have_tablepath)
356 free (tablepath);
357 __nisbind_destroy (&bptr);
358 nis_free_directory (dir);
359 return NULL;
361 first_try = 1;
362 goto again;
365 else
366 ++done;
367 break;
368 case NIS_CBRESULTS:
369 if (cb != NULL)
371 __nis_do_callback (&bptr, &res->cookie, cb);
372 NIS_RES_STATUS (res) = cb->result;
374 if (!(flags & ALL_RESULTS))
375 ++done;
376 else
378 if (!have_tablepath)
380 tablepath = __get_tablepath (ibreq->ibr_name, &bptr);
381 tableptr = tablepath;
382 have_tablepath = 1;
384 if (tableptr == NULL)
386 ++done;
387 break;
389 free (ibreq->ibr_name);
390 ibreq->ibr_name = strsep (&tableptr, ":");
391 if (ibreq->ibr_name == NULL || ibreq->ibr_name[0] == '\0')
393 ibreq->ibr_name = strdup ("");
394 ++done;
396 else
397 ibreq->ibr_name = strdup (ibreq->ibr_name);
398 if (ibreq->ibr_name == NULL)
400 nis_free_request (ibreq);
401 NIS_RES_STATUS (res) = NIS_NOMEMORY;
402 return res;
406 break;
407 case NIS_SYSTEMERROR:
408 case NIS_NOSUCHNAME:
409 case NIS_NOT_ME:
410 /* If we had first tried the old binding, do nothing, but
411 get a new binding */
412 if (!first_try)
414 if (__nisbind_next (&bptr) != NIS_SUCCESS)
416 ++done;
417 break; /* No more servers to search */
419 while (__nisbind_connect (&bptr) != NIS_SUCCESS)
421 if (__nisbind_next (&bptr) != NIS_SUCCESS)
423 ++done;
424 break; /* No more servers to search */
427 goto again;
429 break;
430 default:
431 if (!first_try)
433 /* Try the next domainname if we don't follow a link. */
434 free (ibreq->ibr_name);
435 ibreq->ibr_name = NULL;
436 if (count_links)
438 NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
439 ++done;
440 break;
442 ++name_nr;
443 if (names[name_nr] == NULL)
445 ++done;
446 break;
448 ibreq->ibr_name = strdup (names[name_nr]);
449 if (ibreq->ibr_name == NULL)
451 nis_free_request (ibreq);
452 NIS_RES_STATUS (res) = NIS_NOMEMORY;
453 return res;
455 first_try = 1; /* Try old binding at first */
456 goto again;
458 break;
460 first_try = 0;
462 if (cb)
464 __nis_destroy_callback (cb);
465 ibreq->ibr_cbhost.ibr_cbhost_len = 0;
466 ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
469 __nisbind_destroy (&bptr);
470 nis_free_directory (dir);
473 if (names != namebuf)
474 nis_freenames (names);
476 nis_free_request (ibreq);
478 return res;
480 libnsl_hidden_def (nis_list)
482 nis_result *
483 nis_add_entry (const_nis_name name, const nis_object *obj2, unsigned int flags)
485 nis_object obj;
486 nis_result *res;
487 nis_error status;
488 ib_request *ibreq;
489 size_t namelen = strlen (name);
490 char buf1[namelen + 20];
491 char buf4[namelen + 20];
493 res = calloc (1, sizeof (nis_result));
494 if (res == NULL)
495 return NULL;
497 if (name == NULL)
499 NIS_RES_STATUS (res) = NIS_BADNAME;
500 return res;
503 if ((ibreq = __create_ib_request (name, flags)) == NULL)
505 NIS_RES_STATUS (res) = NIS_BADNAME;
506 return res;
509 memcpy (&obj, obj2, sizeof (nis_object));
511 if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
512 obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
514 if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
515 obj.zo_owner = nis_local_principal ();
517 if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
518 obj.zo_group = nis_local_group ();
520 obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
522 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
523 if (ibreq->ibr_obj.ibr_obj_val == NULL)
525 nis_free_request (ibreq);
526 NIS_RES_STATUS (res) = NIS_NOMEMORY;
527 return res;
529 ibreq->ibr_obj.ibr_obj_len = 1;
531 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBADD,
532 (xdrproc_t) _xdr_ib_request,
533 (caddr_t) ibreq,
534 (xdrproc_t) _xdr_nis_result,
535 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
536 NIS_RES_STATUS (res) = status;
538 nis_free_request (ibreq);
540 return res;
543 nis_result *
544 nis_modify_entry (const_nis_name name, const nis_object *obj2,
545 unsigned int flags)
547 nis_object obj;
548 nis_result *res;
549 nis_error status;
550 ib_request *ibreq;
551 size_t namelen = strlen (name);
552 char buf1[namelen + 20];
553 char buf4[namelen + 20];
555 res = calloc (1, sizeof (nis_result));
556 if (res == NULL)
557 return NULL;
559 if (( ibreq =__create_ib_request (name, flags)) == NULL)
561 NIS_RES_STATUS (res) = NIS_BADNAME;
562 return res;
565 memcpy (&obj, obj2, sizeof (nis_object));
567 if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
568 obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
570 if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
571 obj.zo_owner = nis_local_principal ();
573 if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
574 obj.zo_group = nis_local_group ();
576 obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
578 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
579 if (ibreq->ibr_obj.ibr_obj_val == NULL)
581 nis_free_request (ibreq);
582 NIS_RES_STATUS (res) = NIS_NOMEMORY;
583 return res;
585 ibreq->ibr_obj.ibr_obj_len = 1;
587 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBMODIFY,
588 (xdrproc_t) _xdr_ib_request,
589 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
590 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
591 NIS_RES_STATUS (res) = status;
593 nis_free_request (ibreq);
595 return res;
598 nis_result *
599 nis_remove_entry (const_nis_name name, const nis_object *obj,
600 unsigned int flags)
602 nis_result *res;
603 ib_request *ibreq;
604 nis_error status;
606 res = calloc (1, sizeof (nis_result));
607 if (res == NULL)
608 return NULL;
610 if (name == NULL)
612 NIS_RES_STATUS (res) = NIS_BADNAME;
613 return res;
616 if ((ibreq =__create_ib_request (name, flags)) == NULL)
618 NIS_RES_STATUS (res) = NIS_BADNAME;
619 return res;
622 if (obj != NULL)
624 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
625 if (ibreq->ibr_obj.ibr_obj_val == NULL)
627 nis_free_request (ibreq);
628 NIS_RES_STATUS (res) = NIS_NOMEMORY;
629 return res;
631 ibreq->ibr_obj.ibr_obj_len = 1;
634 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBREMOVE,
635 (xdrproc_t) _xdr_ib_request,
636 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
637 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
638 NIS_RES_STATUS (res) = status;
640 nis_free_request (ibreq);
642 return res;
645 nis_result *
646 nis_first_entry (const_nis_name name)
648 nis_result *res;
649 ib_request *ibreq;
650 nis_error status;
652 res = calloc (1, sizeof (nis_result));
653 if (res == NULL)
654 return NULL;
656 if (name == NULL)
658 NIS_RES_STATUS (res) = NIS_BADNAME;
659 return res;
662 ibreq = __create_ib_request (name, 0);
663 if (ibreq == NULL)
665 NIS_RES_STATUS (res) = NIS_BADNAME;
666 return res;
669 status = __do_niscall (ibreq->ibr_name, NIS_IBFIRST,
670 (xdrproc_t) _xdr_ib_request,
671 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
672 (caddr_t) res, 0, NULL);
674 if (status != NIS_SUCCESS)
675 NIS_RES_STATUS (res) = status;
677 nis_free_request (ibreq);
679 return res;
682 nis_result *
683 nis_next_entry (const_nis_name name, const netobj *cookie)
685 nis_result *res;
686 ib_request *ibreq;
687 nis_error status;
689 res = calloc (1, sizeof (nis_result));
690 if (res == NULL)
691 return NULL;
693 if (name == NULL)
695 NIS_RES_STATUS (res) = NIS_BADNAME;
696 return res;
699 ibreq = __create_ib_request (name, 0);
700 if (ibreq == NULL)
702 NIS_RES_STATUS (res) = NIS_BADNAME;
703 return res;
706 if (cookie != NULL)
708 ibreq->ibr_cookie.n_bytes = cookie->n_bytes;
709 ibreq->ibr_cookie.n_len = cookie->n_len;
712 status = __do_niscall (ibreq->ibr_name, NIS_IBNEXT,
713 (xdrproc_t) _xdr_ib_request,
714 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
715 (caddr_t) res, 0, NULL);
717 if (status != NIS_SUCCESS)
718 NIS_RES_STATUS (res) = status;
720 if (cookie != NULL)
722 /* Don't give cookie free, it is not from us */
723 ibreq->ibr_cookie.n_bytes = NULL;
724 ibreq->ibr_cookie.n_len = 0;
727 nis_free_request (ibreq);
729 return res;