Add NIS+ functions
[kopensolaris-gnu/glibc.git] / nis / nis_table.c
1 /* Copyright (c) 1997 Free Software Foundation, Inc.
2
3    This file is part of the GNU C Library.
4    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public License as
8    published by the Free Software Foundation; either version 2 of the
9    License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15
16    You should have received a copy of the GNU Library General Public
17    License along with the GNU C Library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include <string.h>
22 #include <rpcsvc/nis.h>
23 #include <rpcsvc/nislib.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 (char *));
83           (*srch_val)[*srch_len].zattr_val.zattr_val_len = 0;
84           (*srch_val)[*srch_len].zattr_val.zattr_val_val = NULL;
85           return;
86         }
87
88       val[0] = '\0';
89       val++;
90
91       if ((*srch_len) + 1 >= size)
92         {
93           size += 10;
94           if (size == 10)
95             *srch_val = malloc (size * sizeof (char *));
96           else
97             *srch_val = realloc (val, size * sizeof (char *));
98           if (*srch_val == NULL)
99             {
100               free (cptr);
101               free (*ibr_name);
102               *ibr_name = NULL;
103               return;
104             }
105         }
106
107       (*srch_val)[*srch_len].zattr_ndx = strdup (key);
108       if (((*srch_val)[*srch_len].zattr_ndx) == NULL)
109         {
110           free (cptr);
111           free (*ibr_name);
112           *ibr_name = NULL;
113           return;
114         }
115       (*srch_val)[*srch_len].zattr_val.zattr_val_len = strlen (val) + 1;
116       (*srch_val)[*srch_len].zattr_val.zattr_val_val = strdup (val);
117       if ((*srch_val)[*srch_len].zattr_val.zattr_val_val == NULL)
118         {
119           free (cptr);
120           free (*ibr_name);
121           *ibr_name = NULL;
122           return;
123         }
124       (*srch_len)++;
125
126       key = next;
127
128     }
129   while (next);
130
131   free (cptr);
132   return;
133 }
134
135 static struct ib_request *
136 __create_ib_request (const nis_name name, struct ib_request *ibreq,
137                      u_long flags)
138 {
139   splitname (name, &ibreq->ibr_name, &ibreq->ibr_srch.ibr_srch_len,
140              &ibreq->ibr_srch.ibr_srch_val);
141   if (ibreq->ibr_name == NULL)
142     return NULL;
143   if ((flags & EXPAND_NAME) == EXPAND_NAME)
144     {
145       nis_name *names;
146
147       names = __nis_expandname (ibreq->ibr_name);
148       free (ibreq->ibr_name);
149       ibreq->ibr_name = NULL;
150       if (names == NULL)
151         return NULL;
152       ibreq->ibr_name = strdup (names[0]);
153       nis_freenames (names);
154     }
155
156   ibreq->ibr_flags = (flags & (RETURN_RESULT | ADD_OVERWRITE | REM_MULTIPLE |
157                                MOD_SAMEOBJ | ADD_RESERVED | REM_RESERVED |
158                                MOD_EXCLUSIVE));
159   ibreq->ibr_obj.ibr_obj_len = 0;
160   ibreq->ibr_obj.ibr_obj_val = NULL;
161   ibreq->ibr_cbhost.ibr_cbhost_len = 0;
162   ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
163   ibreq->ibr_bufsize = 0;
164   ibreq->ibr_cookie.n_len = 0;
165   ibreq->ibr_cookie.n_bytes = NULL;
166
167   return ibreq;
168 }
169
170 nis_result *
171 nis_list (const nis_name name, const u_long flags,
172           int (*callback) (const nis_name name,
173                            const nis_object * object,
174                            const void *userdata),
175           const void *userdata)
176 {
177   nis_result *res = NULL;
178   struct ib_request ibreq;
179   int result;
180   int count_links = 0;          /* We will only follow 16 links! */
181   int is_link = 1;              /* We should go at least once in the while loop */
182
183   res = malloc (sizeof (nis_result));
184   memset (res, '\0', sizeof (nis_result));
185
186   if (__create_ib_request (name, &ibreq, flags) == NULL)
187     {
188       res->status = NIS_BADNAME;
189       return res;
190     }
191
192   while (is_link)
193     {
194       memset (res, '\0', sizeof (nis_result));
195
196       if ((result = __do_niscall (NULL, 0, NIS_IBLIST,
197                                   (xdrproc_t) xdr_ib_request,
198                               (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result,
199                                   (caddr_t) res, flags)) != RPC_SUCCESS)
200         {
201           res->status = result;
202           nis_free_request (&ibreq);
203           return res;
204         }
205
206       nis_free_request (&ibreq);
207
208       if ((res->status == NIS_SUCCESS || res->status == NIS_S_SUCCESS) &&
209           (res->objects.objects_len > 0 &&
210            res->objects.objects_val->zo_data.zo_type == LINK_OBJ))
211         is_link = 1;
212       else
213         is_link = 0;
214
215       if (is_link)
216         {
217           if ((flags & FOLLOW_LINKS) == FOLLOW_LINKS)
218             {
219               if (count_links == 16)
220                 {
221                   res->status = NIS_LINKNAMEERROR;
222                   return res;
223                 }
224               else
225                 ++count_links;
226
227               if (__create_ib_request (res->objects.objects_val->LI_data.li_name,
228                                        &ibreq, flags) == NULL)
229                 {
230                   res->status = NIS_BADNAME;
231                   return res;
232                 }
233             }
234           else
235             {
236               res->status = NIS_NOTSEARCHABLE;
237               return res;
238             }
239         }
240     }
241
242   if (callback != NULL &&
243       (res->status == NIS_SUCCESS || res->status == NIS_S_SUCCESS))
244     {
245       unsigned int i;
246
247       for (i = 0; i < res->objects.objects_len; i++)
248         if ((*callback) (name, &(res->objects.objects_val)[i], userdata) != 0)
249           break;
250     }
251
252   return res;
253 }
254
255 nis_result *
256 nis_add_entry (const nis_name name, const nis_object * obj,
257                const u_long flags)
258 {
259   nis_result *res;
260   struct ib_request ibreq;
261   nis_error status;
262
263   res = malloc (sizeof (nis_result));
264   memset (res, '\0', sizeof (nis_result));
265
266   if (__create_ib_request (name, &ibreq, flags) == NULL)
267     {
268       res->status = NIS_BADNAME;
269       return res;
270     }
271
272   ibreq.ibr_flags = flags;
273   ibreq.ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
274   ibreq.ibr_obj.ibr_obj_len = 1;
275
276   if ((status = __do_niscall (NULL, 0, NIS_IBADD,
277                               (xdrproc_t) xdr_ib_request,
278                               (caddr_t) & ibreq,
279                               (xdrproc_t) xdr_nis_result,
280                               (caddr_t) res, 0)) != RPC_SUCCESS)
281     res->status = status;
282
283   nis_free_request (&ibreq);
284
285   return res;
286 }
287
288 nis_result *
289 nis_modify_entry (const nis_name name, const nis_object * obj,
290                   const u_long flags)
291 {
292   nis_result *res;
293   struct ib_request ibreq;
294   nis_error status;
295
296   res = malloc (sizeof (nis_result));
297   memset (res, '\0', sizeof (nis_result));
298
299   if (__create_ib_request (name, &ibreq, flags) == NULL)
300     {
301       res->status = NIS_BADNAME;
302       return res;
303     }
304
305   ibreq.ibr_flags = flags;
306   ibreq.ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
307   ibreq.ibr_obj.ibr_obj_len = 1;
308
309   if ((status = __do_niscall (NULL, 0, NIS_IBMODIFY,
310                               (xdrproc_t) xdr_ib_request,
311                               (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result,
312                               (caddr_t) res, 0)) != RPC_SUCCESS)
313     res->status = status;
314
315   nis_free_request (&ibreq);
316
317   return res;
318 }
319
320 nis_result *
321 nis_remove_entry (const nis_name name, const nis_object * obj,
322                   const u_long flags)
323 {
324   nis_result *res;
325   struct ib_request ibreq;
326   nis_error status;
327
328   res = malloc (sizeof (nis_result));
329   memset (res, '\0', sizeof (nis_result));
330
331   if (__create_ib_request (name, &ibreq, flags) == NULL)
332     {
333       res->status = NIS_BADNAME;
334       return res;
335     }
336
337   ibreq.ibr_flags = flags;
338   if (obj != NULL)
339     {
340       ibreq.ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
341       ibreq.ibr_obj.ibr_obj_len = 1;
342     }
343
344   if ((status = __do_niscall (NULL, 0, NIS_IBREMOVE,
345                               (xdrproc_t) xdr_ib_request,
346                               (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result,
347                               (caddr_t) res, 0)) != RPC_SUCCESS)
348     res->status = status;
349
350   nis_free_request (&ibreq);
351
352   return res;
353 }
354
355 nis_result *
356 nis_first_entry (const nis_name name)
357 {
358   nis_result *res;
359   struct ib_request ibreq;
360   nis_error status;
361
362   res = malloc (sizeof (nis_result));
363   memset (res, '\0', sizeof (nis_result));
364
365   if (__create_ib_request (name, &ibreq, 0) == NULL)
366     {
367       res->status = NIS_BADNAME;
368       return res;
369     }
370
371   if ((status = __do_niscall (NULL, 0, NIS_IBFIRST, (xdrproc_t) xdr_ib_request,
372                               (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result,
373                               (caddr_t) res, 0)) != RPC_SUCCESS)
374     res->status = status;
375
376   nis_free_request (&ibreq);
377
378   return res;
379 }
380
381 nis_result *
382 nis_next_entry (const nis_name name, const netobj * cookie)
383 {
384   nis_result *res;
385   struct ib_request ibreq;
386   nis_error status;
387
388   res = malloc (sizeof (nis_result));
389   memset (res, '\0', sizeof (nis_result));
390
391   if (__create_ib_request (name, &ibreq, 0) == NULL)
392     {
393       res->status = NIS_BADNAME;
394       return res;
395     }
396
397   if (cookie != NULL)
398     {
399       ibreq.ibr_cookie.n_bytes = malloc (cookie->n_len);
400       memcpy (ibreq.ibr_cookie.n_bytes, cookie->n_bytes, cookie->n_len);
401       ibreq.ibr_cookie.n_len = cookie->n_len;
402     }
403
404   if ((status = __do_niscall (NULL, 0, NIS_IBNEXT, (xdrproc_t) xdr_ib_request,
405                               (caddr_t) & ibreq, (xdrproc_t) xdr_nis_result,
406                               (caddr_t) res, 0)) != RPC_SUCCESS)
407     res->status = status;
408
409   nis_free_request (&ibreq);
410
411   return res;
412 }