]> git.ipfire.org Git - thirdparty/glibc.git/blob - nis/nis_table.c
Update.
[thirdparty/glibc.git] / nis / nis_table.c
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.
4
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.
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 Library General Public License for more details.
14
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. */
19
20 #include <string.h>
21 #include <rpcsvc/nis.h>
22
23 #include "nis_xdr.h"
24 #include "nis_intern.h"
25
26 static void
27 splitname (const_nis_name name, nis_name *ibr_name, int *srch_len,
28 nis_attr **srch_val)
29 {
30 char *cptr, *key, *val, *next;
31 int size;
32
33 if (name == NULL)
34 return;
35
36 cptr = strdup (name);
37 if (srch_len)
38 *srch_len = 0;
39 if (srch_val)
40 *srch_val = NULL;
41 size = 0;
42
43 /* Not of "[key=value,key=value,...],foo.." format? */
44 if (cptr[0] != '[')
45 {
46 *ibr_name = cptr;
47 return;
48 }
49
50 *ibr_name = strchr (cptr, ']');
51 if (*ibr_name == NULL || (*ibr_name)[1] != ',')
52 {
53 free (cptr);
54 *ibr_name = NULL;
55 return;
56 }
57
58 *ibr_name[0] = '\0';
59 *ibr_name += 2;
60 *ibr_name = strdup (*ibr_name);
61
62 if (srch_len == NULL || srch_val == NULL)
63 {
64 free (cptr);
65 return;
66 }
67
68 key = (cptr) + 1;
69 do
70 {
71 next = strchr (key, ',');
72 if (next)
73 {
74 next[0] = '\0';
75 ++next;
76 }
77
78 val = strchr (key, '=');
79 if (!val)
80 {
81 free (cptr);
82 *srch_val = malloc (sizeof (nis_attr));
83 if (*srch_val == NULL)
84 {
85 free (cptr);
86 free (*ibr_name);
87 *ibr_name = NULL;
88 return;
89 }
90 (*srch_val)[0].zattr_val.zattr_val_len = 0;
91 (*srch_val)[0].zattr_val.zattr_val_val = NULL;
92 return;
93 }
94
95 val[0] = '\0';
96 ++val;
97
98 if ((*srch_len) + 1 >= size)
99 {
100 size += 10;
101 if (size == 10)
102 *srch_val = malloc (size * sizeof (char *));
103 else
104 *srch_val = realloc (val, size * sizeof (char *));
105 if (*srch_val == NULL)
106 {
107 free (cptr);
108 free (*ibr_name);
109 *ibr_name = NULL;
110 return;
111 }
112 }
113
114 (*srch_val)[*srch_len].zattr_ndx = strdup (key);
115 if (((*srch_val)[*srch_len].zattr_ndx) == NULL)
116 {
117 free (cptr);
118 free (*ibr_name);
119 *ibr_name = NULL;
120 return;
121 }
122 (*srch_val)[*srch_len].zattr_val.zattr_val_len = strlen (val) + 1;
123 (*srch_val)[*srch_len].zattr_val.zattr_val_val = strdup (val);
124 if ((*srch_val)[*srch_len].zattr_val.zattr_val_val == NULL)
125 {
126 free (cptr);
127 free (*ibr_name);
128 *ibr_name = NULL;
129 return;
130 }
131 ++(*srch_len);
132
133 key = next;
134
135 }
136 while (next);
137
138 free (cptr);
139 }
140
141 static struct ib_request *
142 __create_ib_request (const_nis_name name, struct ib_request *ibreq,
143 u_long flags)
144 {
145 splitname (name, &ibreq->ibr_name, &ibreq->ibr_srch.ibr_srch_len,
146 &ibreq->ibr_srch.ibr_srch_val);
147 if (ibreq->ibr_name == NULL)
148 return NULL;
149
150 ibreq->ibr_flags = flags;
151 ibreq->ibr_obj.ibr_obj_len = 0;
152 ibreq->ibr_obj.ibr_obj_val = NULL;
153 ibreq->ibr_cbhost.ibr_cbhost_len = 0;
154 ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
155 ibreq->ibr_bufsize = 0;
156 ibreq->ibr_cookie.n_len = 0;
157 ibreq->ibr_cookie.n_bytes = NULL;
158
159 return ibreq;
160 }
161
162 nis_result *
163 nis_list (const_nis_name name, u_long flags,
164 int (*callback) (const_nis_name name,
165 const nis_object *object,
166 const void *userdata),
167 const void *userdata)
168 {
169 nis_result *res = NULL;
170 ib_request *ibreq = calloc (1, sizeof (ib_request));
171 int status;
172 int count_links = 0; /* We will only follow NIS_MAXLINKS links! */
173 int done = 0;
174 nis_name *names;
175 nis_name namebuf[2] = {NULL, NULL};
176 int name_nr = 0;
177 nis_cb *cb = NULL;
178
179 res = calloc (1, sizeof (nis_result));
180 if (res == NULL)
181 return NULL;
182
183 if (__create_ib_request (name, ibreq, flags) == NULL)
184 {
185 NIS_RES_STATUS (res) = NIS_BADNAME;
186 return res;
187 }
188
189 if (flags & EXPAND_NAME)
190 {
191 names = nis_getnames (ibreq->ibr_name);
192 free (ibreq->ibr_name);
193 ibreq->ibr_name = NULL;
194 if (names == NULL)
195 {
196 NIS_RES_STATUS (res) = NIS_BADNAME;
197 return res;
198 }
199 ibreq->ibr_name = strdup (names[name_nr]);
200 }
201 else
202 {
203 names = namebuf;
204 names[name_nr] = ibreq->ibr_name;
205 }
206
207 cb = NULL;
208
209 if (flags & FOLLOW_PATH || flags & ALL_RESULTS)
210 {
211 nis_result *lres;
212 u_long newflags = flags & ~FOLLOW_PATH & ~ALL_RESULTS;
213 char table_path[NIS_MAXPATH + 1];
214 char *ntable, *p;
215 u_long done = 0, failures = 0;
216
217 while (names[name_nr] != NULL && !done)
218 {
219 lres = nis_lookup (names[name_nr], newflags);
220 if (lres == NULL || NIS_RES_STATUS (lres) != NIS_SUCCESS)
221 {
222 NIS_RES_STATUS (res) = NIS_RES_STATUS (lres);
223 nis_freeresult (lres);
224 ++name_nr;
225 continue;
226 }
227
228 /* nis_lookup handles FOLLOW_LINKS,
229 so we must have a table object. */
230 if (__type_of (NIS_RES_OBJECT (lres)) != NIS_TABLE_OBJ)
231 {
232 nis_freeresult (lres);
233 NIS_RES_STATUS (res) = NIS_INVALIDOBJ;
234 break;
235 }
236
237 /* Save the path, discard everything else. */
238 snprintf (table_path, NIS_MAXPATH, "%s:%s", names[name_nr],
239 NIS_RES_OBJECT (lres)->TA_data.ta_path);
240 nis_freeresult (lres);
241 free (res);
242 res = NULL;
243
244 p = table_path;
245
246 while (((ntable = strsep (&p, ":")) != NULL) && !done)
247 {
248 char *c;
249
250 if (res != NULL)
251 nis_freeresult (res);
252
253 /* Do the job recursive here! */
254 if ((c = strchr(name, ']')) != NULL)
255 {
256 /* Have indexed name ! */
257 int index_len = c - name + 2;
258 char buf[index_len + strlen (ntable) + 1];
259
260 c = __stpncpy (buf, name, index_len);
261 strcpy (c, ntable);
262 res = nis_list (buf, newflags, callback,userdata);
263 }
264 else
265 res = nis_list (ntable, newflags, callback, userdata);
266 if (res == NULL)
267 return NULL;
268 switch (NIS_RES_STATUS (res))
269 {
270 case NIS_SUCCESS:
271 case NIS_CBRESULTS:
272 if (!(flags & ALL_RESULTS))
273 done = 1;
274 break;
275 case NIS_PARTIAL: /* The table is correct, we doesn't found
276 the entry */
277 break;
278 default:
279 if (flags & ALL_RESULTS)
280 ++failures;
281 else
282 done = 1;
283 break;
284 }
285 }
286 if (NIS_RES_STATUS (res) == NIS_SUCCESS && failures)
287 NIS_RES_STATUS (res) = NIS_S_SUCCESS;
288 if (NIS_RES_STATUS (res) == NIS_NOTFOUND && failures)
289 NIS_RES_STATUS (res) = NIS_S_NOTFOUND;
290 break;
291 }
292 }
293 else
294 {
295 if (callback != NULL)
296 {
297 cb = __nis_create_callback (callback, userdata, flags);
298 ibreq->ibr_cbhost.ibr_cbhost_len = 1;
299 ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv;
300 }
301
302 while (!done)
303 {
304 memset (res, '\0', sizeof (nis_result));
305
306 status = __do_niscall (ibreq->ibr_name, NIS_IBLIST,
307 (xdrproc_t) _xdr_ib_request,
308 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
309 (caddr_t) res, flags, cb);
310 if (status != NIS_SUCCESS)
311 NIS_RES_STATUS (res) = status;
312
313 switch (NIS_RES_STATUS (res))
314 {
315 case NIS_PARTIAL:
316 case NIS_SUCCESS:
317 case NIS_S_SUCCESS:
318 if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ &&
319 flags & FOLLOW_LINKS) /* We are following links. */
320 {
321 /* If we hit the link limit, bail. */
322 if (count_links > NIS_MAXLINKS)
323 {
324 NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
325 ++done;
326 break;
327 }
328 if (count_links)
329 free (ibreq->ibr_name);
330 ++count_links;
331 free (ibreq->ibr_name);
332 ibreq->ibr_name =
333 strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
334 if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
335 if (ibreq->ibr_srch.ibr_srch_len == 0)
336 {
337 ibreq->ibr_srch.ibr_srch_len =
338 NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len;
339 ibreq->ibr_srch.ibr_srch_val =
340 NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
341 }
342 nis_freeresult (res);
343 res = calloc (1, sizeof (nis_result));
344 }
345 else
346 ++done;
347 break;
348 case NIS_CBRESULTS:
349 /* Calback is handled in nis_call.c (__do_niscall2),
350 but we have to change the error code */
351 NIS_RES_STATUS (res) = cb->result;
352 ++done;
353 break;
354 case NIS_UNAVAIL:
355 /* NIS+ is not installed, or all servers are down. */
356 ++done;
357 break;
358 default:
359 /* Try the next domainname if we don't follow a link. */
360 if (count_links)
361 {
362 free (ibreq->ibr_name);
363 NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
364 ++done;
365 break;
366 }
367 ++name_nr;
368 if (names[name_nr] == NULL)
369 {
370 ++done;
371 break;
372 }
373 ibreq->ibr_name = names[name_nr];
374 break;
375 }
376 }
377 } /* End of not FOLLOW_PATH. */
378
379 if (names != namebuf)
380 nis_freenames (names);
381
382 if (cb)
383 {
384 __nis_destroy_callback (cb);
385 ibreq->ibr_cbhost.ibr_cbhost_len = 0;
386 ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
387 }
388
389 nis_free_request (ibreq);
390
391 return res;
392 }
393
394 nis_result *
395 nis_add_entry (const_nis_name name, const nis_object *obj2, u_long flags)
396 {
397 nis_object obj;
398 nis_result *res;
399 nis_error status;
400 ib_request *ibreq = calloc (1, sizeof (ib_request));
401 char buf1[strlen (name) + 20];
402 char buf4[strlen (name) + 20];
403
404 res = calloc (1, sizeof (nis_result));
405 if (res == NULL)
406 return NULL;
407
408 if (ibreq == NULL)
409 {
410 NIS_RES_STATUS (res) = NIS_NOMEMORY;
411 return res;
412 }
413
414 if (__create_ib_request (name, ibreq, flags) == NULL)
415 {
416 NIS_RES_STATUS (res) = NIS_BADNAME;
417 return res;
418 }
419
420 memcpy (&obj, obj2, sizeof (nis_object));
421
422 if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
423 obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
424
425 if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
426 obj.zo_owner = nis_local_principal ();
427
428 if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
429 obj.zo_group = nis_local_group ();
430
431 obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
432
433 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
434 if (ibreq->ibr_obj.ibr_obj_val == NULL)
435 {
436 NIS_RES_STATUS (res) = NIS_NOMEMORY;
437 return res;
438 }
439 ibreq->ibr_obj.ibr_obj_len = 1;
440
441 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBADD,
442 (xdrproc_t) _xdr_ib_request,
443 (caddr_t) ibreq,
444 (xdrproc_t) _xdr_nis_result,
445 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
446 NIS_RES_STATUS (res) = status;
447
448 nis_free_request (ibreq);
449
450 return res;
451 }
452
453 nis_result *
454 nis_modify_entry (const_nis_name name, const nis_object *obj2, u_long flags)
455 {
456 nis_object obj;
457 nis_result *res;
458 nis_error status;
459 ib_request *ibreq = calloc (1, sizeof (ib_request));
460 char buf1[strlen (name) + 20];
461 char buf4[strlen (name) + 20];
462
463 res = calloc (1, sizeof (nis_result));
464
465 if (__create_ib_request (name, ibreq, flags) == NULL)
466 {
467 NIS_RES_STATUS (res) = NIS_BADNAME;
468 return res;
469 }
470
471 memcpy (&obj, obj2, sizeof (nis_object));
472
473 if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
474 obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
475
476 if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
477 obj.zo_owner = nis_local_principal ();
478
479 if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
480 obj.zo_group = nis_local_group ();
481
482 obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
483
484 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
485 if (ibreq->ibr_obj.ibr_obj_val == NULL)
486 {
487 NIS_RES_STATUS (res) = NIS_NOMEMORY;
488 return res;
489 }
490 ibreq->ibr_obj.ibr_obj_len = 1;
491
492 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBMODIFY,
493 (xdrproc_t) _xdr_ib_request,
494 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
495 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
496 NIS_RES_STATUS (res) = status;
497
498 nis_free_request (ibreq);
499
500 return res;
501 }
502
503 nis_result *
504 nis_remove_entry (const_nis_name name, const nis_object *obj,
505 u_long flags)
506 {
507 nis_result *res;
508 ib_request *ibreq = calloc (1, sizeof (ib_request));
509 nis_error status;
510
511 res = calloc (1, sizeof (nis_result));
512 if (res == NULL)
513 return NULL;
514
515 if (ibreq == NULL)
516 {
517 NIS_RES_STATUS (res) = NIS_NOMEMORY;
518 return res;
519 }
520
521 if (__create_ib_request (name, ibreq, flags) == NULL)
522 {
523 NIS_RES_STATUS (res) = NIS_BADNAME;
524 return res;
525 }
526
527 if (obj != NULL)
528 {
529 ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
530 if (ibreq->ibr_obj.ibr_obj_val == NULL)
531 {
532 NIS_RES_STATUS (res) = NIS_NOMEMORY;
533 return res;
534 }
535 ibreq->ibr_obj.ibr_obj_len = 1;
536 }
537
538 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBREMOVE,
539 (xdrproc_t) _xdr_ib_request,
540 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
541 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
542 NIS_RES_STATUS (res) = status;
543
544 nis_free_request (ibreq);
545
546 return res;
547 }
548
549 nis_result *
550 nis_first_entry (const_nis_name name)
551 {
552 nis_result *res;
553 ib_request *ibreq = calloc (1, sizeof (ib_request));
554 nis_error status;
555
556 res = calloc (1, sizeof (nis_result));
557 if (res == NULL)
558 return NULL;
559
560 if (ibreq == NULL)
561 {
562 NIS_RES_STATUS (res) = NIS_NOMEMORY;
563 return res;
564 }
565
566 if (__create_ib_request (name, ibreq, 0) == NULL)
567 {
568 NIS_RES_STATUS (res) = NIS_BADNAME;
569 return res;
570 }
571
572 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBFIRST,
573 (xdrproc_t) _xdr_ib_request,
574 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
575 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
576 NIS_RES_STATUS (res) = status;
577
578 nis_free_request (ibreq);
579
580 return res;
581 }
582
583 nis_result *
584 nis_next_entry (const_nis_name name, const netobj *cookie)
585 {
586 nis_result *res;
587 ib_request *ibreq = calloc (1, sizeof (ib_request));
588 nis_error status;
589
590 res = calloc (1, sizeof (nis_result));
591 if (res == NULL)
592 return NULL;
593
594 if (ibreq == NULL)
595 {
596 NIS_RES_STATUS (res) = NIS_NOMEMORY;
597 return res;
598 }
599
600 if (__create_ib_request (name, ibreq, 0) == NULL)
601 {
602 NIS_RES_STATUS (res) = NIS_BADNAME;
603 return res;
604 }
605
606 if (cookie != NULL)
607 {
608 ibreq->ibr_cookie.n_bytes = malloc (cookie->n_len);
609 if (ibreq->ibr_cookie.n_bytes == NULL)
610 {
611 NIS_RES_STATUS (res) = NIS_NOMEMORY;
612 nis_free_request (ibreq);
613 return res;
614 }
615 memcpy (ibreq->ibr_cookie.n_bytes, cookie->n_bytes, cookie->n_len);
616 ibreq->ibr_cookie.n_len = cookie->n_len;
617 }
618
619 if ((status = __do_niscall (ibreq->ibr_name, NIS_IBNEXT,
620 (xdrproc_t) _xdr_ib_request,
621 (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
622 (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
623 NIS_RES_STATUS (res) = status;
624
625 nis_free_request (ibreq);
626
627 return res;
628 }