Update.
[glibc.git] / nis / nis_table.c
blobd2a1df76b2c1273fe0b8b984596b8618a9c60dbb
1 /* Copyright (c) 1997 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)
207 nis_result *lres;
208 u_long newflags = flags & ~FOLLOW_PATH;
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);
241 p = table_path;
243 while (((ntable = strsep (&p, ":")) != NULL) && !done)
245 /* Do the job recursive here! */
246 res = nis_list (name, newflags, callback, userdata);
247 if (res == NULL)
248 return NULL;
249 switch (res->status)
251 case NIS_SUCCESS:
252 case NIS_CBRESULTS:
253 if (!(flags & ALL_RESULTS))
254 done = 1;
255 break;
256 default:
257 if (flags & ALL_RESULTS)
258 failures++;
259 else
260 done = 1;
261 break;
264 if (res->status == NIS_SUCCESS && failures)
265 res->status = NIS_S_SUCCESS;
266 if (res->status == NIS_NOTFOUND && failures)
267 res->status = NIS_S_NOTFOUND;
268 break;
271 else
273 if (callback != NULL)
275 cb = __nis_create_callback (callback, userdata, flags);
276 ibreq->ibr_cbhost.ibr_cbhost_len = 1;
277 ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv;
280 while (!done)
282 memset (res, '\0', sizeof (nis_result));
284 status = __do_niscall (ibreq->ibr_name, NIS_IBLIST,
285 (xdrproc_t) xdr_ib_request,
286 (caddr_t) ibreq, (xdrproc_t) xdr_nis_result,
287 (caddr_t) res, flags, cb);
288 if (status != NIS_SUCCESS)
289 res->status = status;
291 switch (res->status)
293 case NIS_PARTIAL:
294 case NIS_SUCCESS:
295 case NIS_S_SUCCESS:
296 if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ &&
297 flags & FOLLOW_LINKS) /* We are following links. */
299 /* If we hit the link limit, bail. */
300 if (count_links > NIS_MAXLINKS)
302 res->status = NIS_LINKNAMEERROR;
303 ++done;
304 break;
306 if (count_links)
307 free (ibreq->ibr_name);
308 ++count_links;
309 free (ibreq->ibr_name);
310 ibreq->ibr_name =
311 strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
312 if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
313 if (ibreq->ibr_srch.ibr_srch_len == 0)
315 ibreq->ibr_srch.ibr_srch_len =
316 NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len;
317 ibreq->ibr_srch.ibr_srch_val =
318 NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
320 nis_freeresult (res);
321 res = calloc (1, sizeof (nis_result));
323 else
324 ++done;
325 break;
326 case NIS_CBRESULTS:
327 /* Calback is handled in nis_call.c (__do_niscall2). */
328 ++done;
329 break;
330 case NIS_UNAVAIL:
331 /* NIS+ is not installed, or all servers are down. */
332 ++done;
333 break;
334 default:
335 /* Try the next domainname if we don't follow a link. */
336 if (count_links)
338 free (ibreq->ibr_name);
339 res->status = NIS_LINKNAMEERROR;
340 ++done;
341 break;
343 ++name_nr;
344 if (names[name_nr] == NULL)
346 ++done;
347 break;
349 ibreq->ibr_name = names[name_nr];
350 break;
353 } /* End of not FOLLOW_PATH. */
355 if (names != namebuf)
356 nis_freenames (names);
358 if (cb)
360 __nis_destroy_callback (cb);
361 ibreq->ibr_cbhost.ibr_cbhost_len = 0;
362 ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
365 nis_free_request (ibreq);
367 return res;
370 nis_result *
371 nis_add_entry (const_nis_name name, const nis_object *obj,
372 u_long flags)
374 nis_result *res;
375 nis_error status;
376 ib_request *ibreq = calloc (1, sizeof (ib_request));
377 char *p1, *p2, *p3, *p4;
378 char buf1[strlen (name) + 20];
379 char buf4[strlen (name) + 20];
381 res = calloc (1, sizeof (nis_result));
383 if (__create_ib_request (name, ibreq, flags) == NULL)
385 res->status = NIS_BADNAME;
386 return res;
389 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
390 ibreq->ibr_obj.ibr_obj_len = 1;
392 p1 = ibreq->ibr_obj.ibr_obj_val->zo_name;
393 if (p1 == NULL || strlen (p1) == 0)
394 ibreq->ibr_obj.ibr_obj_val->zo_name =
395 nis_leaf_of_r (name, buf1, sizeof (buf1));
397 p2 = ibreq->ibr_obj.ibr_obj_val->zo_owner;
398 if (p2 == NULL || strlen (p2) == 0)
399 ibreq->ibr_obj.ibr_obj_val->zo_owner = nis_local_principal ();
401 p3 = ibreq->ibr_obj.ibr_obj_val->zo_group;
402 if (p3 == NULL || strlen (p3) == 0)
403 ibreq->ibr_obj.ibr_obj_val->zo_group = nis_local_group ();
405 p4 = ibreq->ibr_obj.ibr_obj_val->zo_domain;
406 ibreq->ibr_obj.ibr_obj_val->zo_domain =
407 nis_domain_of_r (name, buf4, sizeof (buf4));
409 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBADD,
410 (xdrproc_t) xdr_ib_request,
411 (caddr_t) ibreq,
412 (xdrproc_t) xdr_nis_result,
413 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
414 res->status = status;
416 ibreq->ibr_obj.ibr_obj_val->zo_name = p1;
417 ibreq->ibr_obj.ibr_obj_val->zo_owner = p2;
418 ibreq->ibr_obj.ibr_obj_val->zo_group = p3;
419 ibreq->ibr_obj.ibr_obj_val->zo_domain = p4;
421 nis_free_request (ibreq);
423 return res;
426 nis_result *
427 nis_modify_entry (const_nis_name name, const nis_object *obj,
428 u_long flags)
430 nis_result *res;
431 nis_error status;
432 ib_request *ibreq = calloc (1, sizeof (ib_request));
433 char *p1, *p2, *p3, *p4;
434 char buf1[strlen (name) + 20];
435 char buf4[strlen (name) + 20];
437 res = calloc (1, sizeof (nis_result));
439 if (__create_ib_request (name, ibreq, flags) == NULL)
441 res->status = NIS_BADNAME;
442 return res;
445 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
446 ibreq->ibr_obj.ibr_obj_len = 1;
448 p1 = ibreq->ibr_obj.ibr_obj_val->zo_name;
449 if (p1 == NULL || strlen (p1) == 0)
450 ibreq->ibr_obj.ibr_obj_val->zo_name =
451 nis_leaf_of_r (name, buf1, sizeof (buf1));
453 p2 = ibreq->ibr_obj.ibr_obj_val->zo_owner;
454 if (p2 == NULL || strlen (p2) == 0)
455 ibreq->ibr_obj.ibr_obj_val->zo_owner = nis_local_principal ();
457 p3 = ibreq->ibr_obj.ibr_obj_val->zo_group;
458 if (p3 == NULL || strlen (p3) == 0)
459 ibreq->ibr_obj.ibr_obj_val->zo_group = nis_local_group ();
461 p4 = ibreq->ibr_obj.ibr_obj_val->zo_domain;
462 ibreq->ibr_obj.ibr_obj_val->zo_domain =
463 nis_domain_of_r (name, buf4, sizeof (buf4));
465 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBMODIFY,
466 (xdrproc_t) xdr_ib_request,
467 (caddr_t) ibreq, (xdrproc_t) xdr_nis_result,
468 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
469 res->status = status;
471 ibreq->ibr_obj.ibr_obj_val->zo_name = p1;
472 ibreq->ibr_obj.ibr_obj_val->zo_owner = p2;
473 ibreq->ibr_obj.ibr_obj_val->zo_group = p3;
474 ibreq->ibr_obj.ibr_obj_val->zo_domain = p4;
476 nis_free_request (ibreq);
478 return res;
481 nis_result *
482 nis_remove_entry (const_nis_name name, const nis_object *obj,
483 u_long flags)
485 nis_result *res;
486 ib_request *ibreq = calloc (1, sizeof (ib_request));
487 nis_error status;
489 res = calloc (1, sizeof (nis_result));
491 if (__create_ib_request (name, ibreq, flags) == NULL)
493 res->status = NIS_BADNAME;
494 return res;
497 if (obj != NULL)
499 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
500 ibreq->ibr_obj.ibr_obj_len = 1;
503 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBREMOVE,
504 (xdrproc_t) xdr_ib_request,
505 (caddr_t) ibreq, (xdrproc_t) xdr_nis_result,
506 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
507 res->status = status;
509 nis_free_request (ibreq);
511 return res;
514 nis_result *
515 nis_first_entry (const_nis_name name)
517 nis_result *res;
518 ib_request *ibreq = calloc (1, sizeof (ib_request));
519 nis_error status;
521 res = calloc (1, sizeof (nis_result));
523 if (__create_ib_request (name, ibreq, 0) == NULL)
525 res->status = NIS_BADNAME;
526 return res;
529 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBFIRST,
530 (xdrproc_t) xdr_ib_request,
531 (caddr_t) ibreq, (xdrproc_t) xdr_nis_result,
532 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
533 res->status = status;
535 nis_free_request (ibreq);
537 return res;
540 nis_result *
541 nis_next_entry (const_nis_name name, const netobj *cookie)
543 nis_result *res;
544 ib_request *ibreq = calloc (1, sizeof (ib_request));
545 nis_error status;
547 res = calloc (1, sizeof (nis_result));
549 if (__create_ib_request (name, ibreq, 0) == NULL)
551 res->status = NIS_BADNAME;
552 return res;
555 if (cookie != NULL)
557 ibreq->ibr_cookie.n_bytes = malloc (cookie->n_len);
558 if (ibreq->ibr_cookie.n_bytes == NULL)
560 res->status = NIS_NOMEMORY;
561 free (res);
562 return NULL;
564 memcpy (ibreq->ibr_cookie.n_bytes, cookie->n_bytes, cookie->n_len);
565 ibreq->ibr_cookie.n_len = cookie->n_len;
568 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBNEXT,
569 (xdrproc_t) xdr_ib_request,
570 (caddr_t) ibreq, (xdrproc_t) xdr_nis_result,
571 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
572 res->status = status;
574 nis_free_request (ibreq);
576 return res;