Update.
[glibc.git] / nis / nis_table.c
blob084ce681934636dae951689ba39448eddd8205b9
1 /* Copyright (c) 1997, 1998 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 Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <string.h>
21 #include <rpcsvc/nis.h>
22 #include "nis_intern.h"
24 static void
25 splitname (const_nis_name name, nis_name *ibr_name, int *srch_len,
26 nis_attr **srch_val)
28 char *cptr, *key, *val, *next;
29 int size;
31 if (name == NULL)
32 return;
34 cptr = strdup (name);
35 if (srch_len)
36 *srch_len = 0;
37 if (srch_val)
38 *srch_val = NULL;
39 size = 0;
41 /* Not of "[key=value,key=value,...],foo.." format? */
42 if (cptr[0] != '[')
44 *ibr_name = cptr;
45 return;
48 *ibr_name = strchr (cptr, ']');
49 if (*ibr_name == NULL || (*ibr_name)[1] != ',')
51 free (cptr);
52 *ibr_name = NULL;
53 return;
56 *ibr_name[0] = '\0';
57 *ibr_name += 2;
58 *ibr_name = strdup (*ibr_name);
60 if (srch_len == NULL || srch_val == NULL)
62 free (cptr);
63 return;
66 key = (cptr) + 1;
69 next = strchr (key, ',');
70 if (next)
72 next[0] = '\0';
73 ++next;
76 val = strchr (key, '=');
77 if (!val)
79 free (cptr);
80 *srch_val = malloc (sizeof (nis_attr));
81 if (*srch_val == NULL)
83 free (cptr);
84 free (*ibr_name);
85 *ibr_name = NULL;
86 return;
88 (*srch_val)[0].zattr_val.zattr_val_len = 0;
89 (*srch_val)[0].zattr_val.zattr_val_val = NULL;
90 return;
93 val[0] = '\0';
94 ++val;
96 if ((*srch_len) + 1 >= size)
98 size += 10;
99 if (size == 10)
100 *srch_val = malloc (size * sizeof (char *));
101 else
102 *srch_val = realloc (val, size * sizeof (char *));
103 if (*srch_val == NULL)
105 free (cptr);
106 free (*ibr_name);
107 *ibr_name = NULL;
108 return;
112 (*srch_val)[*srch_len].zattr_ndx = strdup (key);
113 if (((*srch_val)[*srch_len].zattr_ndx) == NULL)
115 free (cptr);
116 free (*ibr_name);
117 *ibr_name = NULL;
118 return;
120 (*srch_val)[*srch_len].zattr_val.zattr_val_len = strlen (val) + 1;
121 (*srch_val)[*srch_len].zattr_val.zattr_val_val = strdup (val);
122 if ((*srch_val)[*srch_len].zattr_val.zattr_val_val == NULL)
124 free (cptr);
125 free (*ibr_name);
126 *ibr_name = NULL;
127 return;
129 ++(*srch_len);
131 key = next;
134 while (next);
136 free (cptr);
139 static struct ib_request *
140 __create_ib_request (const_nis_name name, struct ib_request *ibreq,
141 u_long flags)
143 splitname (name, &ibreq->ibr_name, &ibreq->ibr_srch.ibr_srch_len,
144 &ibreq->ibr_srch.ibr_srch_val);
145 if (ibreq->ibr_name == NULL)
146 return NULL;
148 ibreq->ibr_flags = flags;
149 ibreq->ibr_obj.ibr_obj_len = 0;
150 ibreq->ibr_obj.ibr_obj_val = NULL;
151 ibreq->ibr_cbhost.ibr_cbhost_len = 0;
152 ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
153 ibreq->ibr_bufsize = 0;
154 ibreq->ibr_cookie.n_len = 0;
155 ibreq->ibr_cookie.n_bytes = NULL;
157 return ibreq;
160 nis_result *
161 nis_list (const_nis_name name, u_long flags,
162 int (*callback) (const_nis_name name,
163 const nis_object *object,
164 const void *userdata),
165 const void *userdata)
167 nis_result *res = NULL;
168 ib_request *ibreq = calloc (1, sizeof (ib_request));
169 int status;
170 int count_links = 0; /* We will only follow NIS_MAXLINKS links! */
171 int done = 0;
172 nis_name *names;
173 nis_name namebuf[2] = {NULL, NULL};
174 int name_nr = 0;
175 nis_cb *cb = NULL;
177 res = calloc (1, sizeof (nis_result));
179 if (__create_ib_request (name, ibreq, flags) == NULL)
181 res->status = NIS_BADNAME;
182 return res;
185 if (flags & EXPAND_NAME)
187 names = nis_getnames (ibreq->ibr_name);
188 free (ibreq->ibr_name);
189 ibreq->ibr_name = NULL;
190 if (names == NULL)
192 res->status = NIS_BADNAME;
193 return res;
195 ibreq->ibr_name = strdup (names[name_nr]);
197 else
199 names = namebuf;
200 names[name_nr] = ibreq->ibr_name;
203 cb = NULL;
205 if (flags & FOLLOW_PATH || flags & ALL_RESULTS)
207 nis_result *lres;
208 u_long newflags = flags & ~FOLLOW_PATH & ~ALL_RESULTS;
209 char table_path[NIS_MAXPATH + 1];
210 char *ntable, *p;
211 u_long done = 0, failures = 0;
213 memset (res, '\0', sizeof (nis_result));
215 while (names[name_nr] != NULL && !done)
217 lres = nis_lookup (names[name_nr], newflags);
218 if (lres == NULL || lres->status != NIS_SUCCESS)
220 res->status = lres->status;
221 nis_freeresult (lres);
222 ++name_nr;
223 continue;
226 /* nis_lookup handles FOLLOW_LINKS,
227 so we must have a table object. */
228 if (__type_of (NIS_RES_OBJECT (lres)) != NIS_TABLE_OBJ)
230 nis_freeresult (lres);
231 res->status = NIS_INVALIDOBJ;
232 break;
235 /* Save the path, discard everything else. */
236 snprintf (table_path, NIS_MAXPATH, "%s:%s", names[name_nr],
237 NIS_RES_OBJECT (lres)->TA_data.ta_path);
238 nis_freeresult (lres);
239 free (res);
240 res = NULL;
242 p = table_path;
244 while (((ntable = strsep (&p, ":")) != NULL) && !done)
246 char *c;
248 if (res != NULL)
249 nis_freeresult (res);
251 /* Do the job recursive here! */
252 if ((c = strchr(name, ']')) != NULL)
254 /* Have indexed name ! */
255 int index_len = c - name + 2;
256 char buf[index_len + strlen (ntable) + 1];
258 c = __stpncpy (buf, name, index_len);
259 strcpy (c, ntable);
260 res = nis_list (buf, newflags, callback,userdata);
262 else
263 res = nis_list (ntable, newflags, callback, userdata);
264 if (res == NULL)
265 return NULL;
266 switch (res->status)
268 case NIS_SUCCESS:
269 case NIS_CBRESULTS:
270 if (!(flags & ALL_RESULTS))
271 done = 1;
272 break;
273 case NIS_PARTIAL: /* The table is correct, we doesn't found
274 the entry */
275 break;
276 default:
277 if (flags & ALL_RESULTS)
278 ++failures;
279 else
280 done = 1;
281 break;
284 if (res->status == NIS_SUCCESS && failures)
285 res->status = NIS_S_SUCCESS;
286 if (res->status == NIS_NOTFOUND && failures)
287 res->status = NIS_S_NOTFOUND;
288 break;
291 else
293 if (callback != NULL)
295 cb = __nis_create_callback (callback, userdata, flags);
296 ibreq->ibr_cbhost.ibr_cbhost_len = 1;
297 ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv;
300 while (!done)
302 memset (res, '\0', sizeof (nis_result));
304 status = __do_niscall (ibreq->ibr_name, NIS_IBLIST,
305 (xdrproc_t) xdr_ib_request,
306 (caddr_t) ibreq, (xdrproc_t) xdr_nis_result,
307 (caddr_t) res, flags, cb);
308 if (status != NIS_SUCCESS)
309 res->status = status;
311 switch (res->status)
313 case NIS_PARTIAL:
314 case NIS_SUCCESS:
315 case NIS_S_SUCCESS:
316 if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ &&
317 flags & FOLLOW_LINKS) /* We are following links. */
319 /* If we hit the link limit, bail. */
320 if (count_links > NIS_MAXLINKS)
322 res->status = NIS_LINKNAMEERROR;
323 ++done;
324 break;
326 if (count_links)
327 free (ibreq->ibr_name);
328 ++count_links;
329 free (ibreq->ibr_name);
330 ibreq->ibr_name =
331 strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
332 if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
333 if (ibreq->ibr_srch.ibr_srch_len == 0)
335 ibreq->ibr_srch.ibr_srch_len =
336 NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len;
337 ibreq->ibr_srch.ibr_srch_val =
338 NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
340 nis_freeresult (res);
341 res = calloc (1, sizeof (nis_result));
343 else
344 ++done;
345 break;
346 case NIS_CBRESULTS:
347 /* Calback is handled in nis_call.c (__do_niscall2). */
348 ++done;
349 break;
350 case NIS_UNAVAIL:
351 /* NIS+ is not installed, or all servers are down. */
352 ++done;
353 break;
354 default:
355 /* Try the next domainname if we don't follow a link. */
356 if (count_links)
358 free (ibreq->ibr_name);
359 res->status = NIS_LINKNAMEERROR;
360 ++done;
361 break;
363 ++name_nr;
364 if (names[name_nr] == NULL)
366 ++done;
367 break;
369 ibreq->ibr_name = names[name_nr];
370 break;
373 } /* End of not FOLLOW_PATH. */
375 if (names != namebuf)
376 nis_freenames (names);
378 if (cb)
380 __nis_destroy_callback (cb);
381 ibreq->ibr_cbhost.ibr_cbhost_len = 0;
382 ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
385 nis_free_request (ibreq);
387 return res;
390 nis_result *
391 nis_add_entry (const_nis_name name, const nis_object *obj,
392 u_long flags)
394 nis_result *res;
395 nis_error status;
396 ib_request *ibreq = calloc (1, sizeof (ib_request));
397 char *p1, *p2, *p3, *p4;
398 char buf1[strlen (name) + 20];
399 char buf4[strlen (name) + 20];
401 res = calloc (1, sizeof (nis_result));
403 if (__create_ib_request (name, ibreq, flags) == NULL)
405 res->status = NIS_BADNAME;
406 return res;
409 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
410 ibreq->ibr_obj.ibr_obj_len = 1;
412 p1 = ibreq->ibr_obj.ibr_obj_val->zo_name;
413 if (p1 == NULL || strlen (p1) == 0)
414 ibreq->ibr_obj.ibr_obj_val->zo_name =
415 nis_leaf_of_r (name, buf1, sizeof (buf1));
417 p2 = ibreq->ibr_obj.ibr_obj_val->zo_owner;
418 if (p2 == NULL || strlen (p2) == 0)
419 ibreq->ibr_obj.ibr_obj_val->zo_owner = nis_local_principal ();
421 p3 = ibreq->ibr_obj.ibr_obj_val->zo_group;
422 if (p3 == NULL || strlen (p3) == 0)
423 ibreq->ibr_obj.ibr_obj_val->zo_group = nis_local_group ();
425 p4 = ibreq->ibr_obj.ibr_obj_val->zo_domain;
426 ibreq->ibr_obj.ibr_obj_val->zo_domain =
427 nis_domain_of_r (name, buf4, sizeof (buf4));
429 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBADD,
430 (xdrproc_t) xdr_ib_request,
431 (caddr_t) ibreq,
432 (xdrproc_t) xdr_nis_result,
433 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
434 res->status = status;
436 ibreq->ibr_obj.ibr_obj_val->zo_name = p1;
437 ibreq->ibr_obj.ibr_obj_val->zo_owner = p2;
438 ibreq->ibr_obj.ibr_obj_val->zo_group = p3;
439 ibreq->ibr_obj.ibr_obj_val->zo_domain = p4;
441 nis_free_request (ibreq);
443 return res;
446 nis_result *
447 nis_modify_entry (const_nis_name name, const nis_object *obj,
448 u_long flags)
450 nis_result *res;
451 nis_error status;
452 ib_request *ibreq = calloc (1, sizeof (ib_request));
453 char *p1, *p2, *p3, *p4;
454 char buf1[strlen (name) + 20];
455 char buf4[strlen (name) + 20];
457 res = calloc (1, sizeof (nis_result));
459 if (__create_ib_request (name, ibreq, flags) == NULL)
461 res->status = NIS_BADNAME;
462 return res;
465 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
466 ibreq->ibr_obj.ibr_obj_len = 1;
468 p1 = ibreq->ibr_obj.ibr_obj_val->zo_name;
469 if (p1 == NULL || strlen (p1) == 0)
470 ibreq->ibr_obj.ibr_obj_val->zo_name =
471 nis_leaf_of_r (name, buf1, sizeof (buf1));
473 p2 = ibreq->ibr_obj.ibr_obj_val->zo_owner;
474 if (p2 == NULL || strlen (p2) == 0)
475 ibreq->ibr_obj.ibr_obj_val->zo_owner = nis_local_principal ();
477 p3 = ibreq->ibr_obj.ibr_obj_val->zo_group;
478 if (p3 == NULL || strlen (p3) == 0)
479 ibreq->ibr_obj.ibr_obj_val->zo_group = nis_local_group ();
481 p4 = ibreq->ibr_obj.ibr_obj_val->zo_domain;
482 ibreq->ibr_obj.ibr_obj_val->zo_domain =
483 nis_domain_of_r (name, buf4, sizeof (buf4));
485 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBMODIFY,
486 (xdrproc_t) xdr_ib_request,
487 (caddr_t) ibreq, (xdrproc_t) xdr_nis_result,
488 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
489 res->status = status;
491 ibreq->ibr_obj.ibr_obj_val->zo_name = p1;
492 ibreq->ibr_obj.ibr_obj_val->zo_owner = p2;
493 ibreq->ibr_obj.ibr_obj_val->zo_group = p3;
494 ibreq->ibr_obj.ibr_obj_val->zo_domain = p4;
496 nis_free_request (ibreq);
498 return res;
501 nis_result *
502 nis_remove_entry (const_nis_name name, const nis_object *obj,
503 u_long flags)
505 nis_result *res;
506 ib_request *ibreq = calloc (1, sizeof (ib_request));
507 nis_error status;
509 res = calloc (1, sizeof (nis_result));
511 if (__create_ib_request (name, ibreq, flags) == NULL)
513 res->status = NIS_BADNAME;
514 return res;
517 if (obj != NULL)
519 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
520 ibreq->ibr_obj.ibr_obj_len = 1;
523 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBREMOVE,
524 (xdrproc_t) xdr_ib_request,
525 (caddr_t) ibreq, (xdrproc_t) xdr_nis_result,
526 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
527 res->status = status;
529 nis_free_request (ibreq);
531 return res;
534 nis_result *
535 nis_first_entry (const_nis_name name)
537 nis_result *res;
538 ib_request *ibreq = calloc (1, sizeof (ib_request));
539 nis_error status;
541 res = calloc (1, sizeof (nis_result));
543 if (__create_ib_request (name, ibreq, 0) == NULL)
545 res->status = NIS_BADNAME;
546 return res;
549 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBFIRST,
550 (xdrproc_t) xdr_ib_request,
551 (caddr_t) ibreq, (xdrproc_t) xdr_nis_result,
552 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
553 res->status = status;
555 nis_free_request (ibreq);
557 return res;
560 nis_result *
561 nis_next_entry (const_nis_name name, const netobj *cookie)
563 nis_result *res;
564 ib_request *ibreq = calloc (1, sizeof (ib_request));
565 nis_error status;
567 res = calloc (1, sizeof (nis_result));
569 if (__create_ib_request (name, ibreq, 0) == NULL)
571 res->status = NIS_BADNAME;
572 return res;
575 if (cookie != NULL)
577 ibreq->ibr_cookie.n_bytes = malloc (cookie->n_len);
578 if (ibreq->ibr_cookie.n_bytes == NULL)
580 res->status = NIS_NOMEMORY;
581 free (res);
582 return NULL;
584 memcpy (ibreq->ibr_cookie.n_bytes, cookie->n_bytes, cookie->n_len);
585 ibreq->ibr_cookie.n_len = cookie->n_len;
588 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBNEXT,
589 (xdrproc_t) xdr_ib_request,
590 (caddr_t) ibreq, (xdrproc_t) xdr_nis_result,
591 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
592 res->status = status;
594 nis_free_request (ibreq);
596 return res;