Back to index

glibc  2.9
nis_table.c
Go to the documentation of this file.
00001 /* Copyright (c) 1997-1999, 2003, 2004, 2005, 2006, 2007
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997.
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <assert.h>
00022 #include <string.h>
00023 #include <rpcsvc/nis.h>
00024 
00025 #include "nis_xdr.h"
00026 #include "nis_intern.h"
00027 #include "libnsl.h"
00028 
00029 
00030 struct ib_request *
00031 __create_ib_request (const_nis_name name, unsigned int flags)
00032 {
00033   struct ib_request *ibreq = calloc (1, sizeof (struct ib_request));
00034   nis_attr *search_val = NULL;
00035   size_t search_len = 0;
00036   size_t size = 0;
00037 
00038   if (ibreq == NULL)
00039     return NULL;
00040 
00041   ibreq->ibr_flags = flags;
00042 
00043   char *cptr = strdupa (name);
00044 
00045   /* Not of "[key=value,key=value,...],foo.." format? */
00046   if (cptr[0] != '[')
00047     {
00048       ibreq->ibr_name = strdup (cptr);
00049       if (ibreq->ibr_name == NULL)
00050        {
00051          free (ibreq);
00052          return NULL;
00053        }
00054       return ibreq;
00055     }
00056 
00057   /* "[key=value,...],foo" format */
00058   ibreq->ibr_name = strchr (cptr, ']');
00059   if (ibreq->ibr_name == NULL || ibreq->ibr_name[1] != ',')
00060     {
00061       /* The object has not really been built yet so we use free.  */
00062       free (ibreq);
00063       return NULL;
00064     }
00065 
00066   /* Check if we have an entry of "[key=value,],bar".  If, remove the "," */
00067   if (ibreq->ibr_name[-1] == ',')
00068     ibreq->ibr_name[-1] = '\0';
00069   else
00070     ibreq->ibr_name[0] = '\0';
00071   ibreq->ibr_name += 2;
00072   ibreq->ibr_name = strdup (ibreq->ibr_name);
00073   if (ibreq->ibr_name == NULL)
00074     {
00075     free_null:
00076       while (search_len-- > 0)
00077        {
00078          free (search_val[search_len].zattr_ndx);
00079          free (search_val[search_len].zattr_val.zattr_val_val);
00080        }
00081       free (search_val);
00082       nis_free_request (ibreq);
00083       return NULL;
00084     }
00085 
00086   ++cptr; /* Remove "[" */
00087 
00088   while (cptr != NULL && cptr[0] != '\0')
00089     {
00090       char *key = cptr;
00091       char *val = strchr (cptr, '=');
00092 
00093       cptr = strchr (key, ',');
00094       if (cptr != NULL)
00095        *cptr++ = '\0';
00096 
00097       if (__builtin_expect (val == NULL, 0))
00098        {
00099          nis_free_request (ibreq);
00100          return NULL;
00101        }
00102       *val++ = '\0';
00103       if (search_len + 1 >= size)
00104         {
00105           size += 1;
00106          nis_attr *newp = realloc (search_val, size * sizeof (nis_attr));
00107          if (newp == NULL)
00108            goto free_null;
00109          search_val = newp;
00110        }
00111       search_val[search_len].zattr_ndx = strdup (key);
00112       if (search_val[search_len].zattr_ndx == NULL)
00113        goto free_null;
00114 
00115       search_val[search_len].zattr_val.zattr_val_len = strlen (val) + 1;
00116       search_val[search_len].zattr_val.zattr_val_val = strdup (val);
00117       if (search_val[search_len].zattr_val.zattr_val_val == NULL)
00118        {
00119          free (search_val[search_len].zattr_ndx);
00120          goto free_null;
00121        }
00122 
00123       ++search_len;
00124     }
00125 
00126   ibreq->ibr_srch.ibr_srch_val = search_val;
00127   ibreq->ibr_srch.ibr_srch_len = search_len;
00128 
00129   return ibreq;
00130 }
00131 libnsl_hidden_def (__create_ib_request)
00132 
00133 static const struct timeval RPCTIMEOUT = {10, 0};
00134 
00135 static char *
00136 get_tablepath (char *name, dir_binding *bptr)
00137 {
00138   enum clnt_stat result;
00139   nis_result res;
00140   struct ns_request req;
00141 
00142   memset (&res, '\0', sizeof (res));
00143 
00144   req.ns_name = name;
00145   req.ns_object.ns_object_len = 0;
00146   req.ns_object.ns_object_val = NULL;
00147 
00148   result = clnt_call (bptr->clnt, NIS_LOOKUP, (xdrproc_t) _xdr_ns_request,
00149                     (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
00150                     (caddr_t) &res, RPCTIMEOUT);
00151 
00152   const char *cptr;
00153   if (result == RPC_SUCCESS && NIS_RES_STATUS (&res) == NIS_SUCCESS
00154       && __type_of (NIS_RES_OBJECT (&res)) == NIS_TABLE_OBJ)
00155     cptr = NIS_RES_OBJECT (&res)->TA_data.ta_path;
00156   else
00157     cptr = "";
00158 
00159   char *str = strdup (cptr);
00160 
00161   if (result == RPC_SUCCESS)
00162     xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &res);
00163 
00164   return str;
00165 }
00166 
00167 
00168 nis_error
00169 __follow_path (char **tablepath, char **tableptr, struct ib_request *ibreq,
00170               dir_binding *bptr)
00171 {
00172   if (*tablepath == NULL)
00173     {
00174       *tablepath = get_tablepath (ibreq->ibr_name, bptr);
00175       if (*tablepath == NULL)
00176        return NIS_NOMEMORY;
00177 
00178       *tableptr = *tablepath;
00179     }
00180   if (*tableptr == NULL)
00181     return NIS_NOTFOUND;
00182 
00183   char *newname = strsep (tableptr, ":");
00184   if (newname[0] == '\0')
00185     return NIS_NOTFOUND;
00186 
00187   newname = strdup (newname);
00188   if (newname == NULL)
00189     return NIS_NOMEMORY;
00190 
00191   free (ibreq->ibr_name);
00192   ibreq->ibr_name = newname;
00193 
00194   return NIS_SUCCESS;
00195 }
00196 libnsl_hidden_def (__follow_path)
00197 
00198 
00199 nis_result *
00200 nis_list (const_nis_name name, unsigned int flags,
00201          int (*callback) (const_nis_name name,
00202                         const nis_object *object,
00203                         const void *userdata),
00204          const void *userdata)
00205 {
00206   nis_result *res = malloc (sizeof (nis_result));
00207   ib_request *ibreq;
00208   int status;
00209   enum clnt_stat clnt_status;
00210   int count_links = 0;             /* We will only follow NIS_MAXLINKS links! */
00211   int done = 0;
00212   nis_name *names;
00213   nis_name namebuf[2] = {NULL, NULL};
00214   int name_nr = 0;
00215   nis_cb *cb = NULL;
00216   char *tableptr;
00217   char *tablepath = NULL;
00218   int first_try = 0; /* Do we try the old binding at first ? */
00219   nis_result *allres = NULL;
00220 
00221   if (res == NULL)
00222     return NULL;
00223 
00224   if (name == NULL)
00225     {
00226       status = NIS_BADNAME;
00227     err_out:
00228       nis_freeresult (allres);
00229       memset (res, '\0', sizeof (nis_result));
00230       NIS_RES_STATUS (res) = status;
00231       return res;
00232     }
00233 
00234   ibreq = __create_ib_request (name, flags);
00235   if (ibreq == NULL)
00236     {
00237       status = NIS_BADNAME;
00238       goto err_out;
00239     }
00240 
00241   if ((flags & EXPAND_NAME)
00242       && ibreq->ibr_name[strlen (ibreq->ibr_name) - 1] != '.')
00243     {
00244       names = nis_getnames (ibreq->ibr_name);
00245       free (ibreq->ibr_name);
00246       ibreq->ibr_name = NULL;
00247       if (names == NULL)
00248        {
00249          nis_free_request (ibreq);
00250          status = NIS_BADNAME;
00251          goto err_out;
00252        }
00253       ibreq->ibr_name = strdup (names[name_nr]);
00254       if (ibreq->ibr_name == NULL)
00255        {
00256          nis_freenames (names);
00257          nis_free_request (ibreq);
00258          status = NIS_NOMEMORY;
00259          goto err_out;
00260        }
00261     }
00262   else
00263     {
00264       names = namebuf;
00265       names[name_nr] = ibreq->ibr_name;
00266     }
00267 
00268   cb = NULL;
00269 
00270   while (!done)
00271     {
00272       dir_binding bptr;
00273       directory_obj *dir = NULL;
00274 
00275       memset (res, '\0', sizeof (nis_result));
00276 
00277       status = __nisfind_server (ibreq->ibr_name,
00278                              ibreq->ibr_srch.ibr_srch_val != NULL,
00279                              &dir, &bptr, flags & ~MASTER_ONLY);
00280       if (status != NIS_SUCCESS)
00281        {
00282           NIS_RES_STATUS (res) = status;
00283           goto fail3;
00284        }
00285 
00286       while (__nisbind_connect (&bptr) != NIS_SUCCESS)
00287        if (__builtin_expect (__nisbind_next (&bptr) != NIS_SUCCESS, 0))
00288          {
00289            NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
00290            goto fail;
00291          }
00292 
00293       if (callback != NULL)
00294        {
00295          assert (cb == NULL);
00296          cb = __nis_create_callback (callback, userdata, flags);
00297          ibreq->ibr_cbhost.ibr_cbhost_len = 1;
00298          ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv;
00299        }
00300 
00301     again:
00302       clnt_status = clnt_call (bptr.clnt, NIS_IBLIST,
00303                             (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq,
00304                             (xdrproc_t) _xdr_nis_result,
00305                             (caddr_t) res, RPCTIMEOUT);
00306 
00307       if (__builtin_expect (clnt_status != RPC_SUCCESS, 0))
00308        NIS_RES_STATUS (res) = NIS_RPCERROR;
00309       else
00310        switch (NIS_RES_STATUS (res))
00311          { /* start switch */
00312          case NIS_PARTIAL:
00313          case NIS_SUCCESS:
00314          case NIS_S_SUCCESS:
00315            if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
00316               && (flags & FOLLOW_LINKS))  /* We are following links.  */
00317              {
00318               free (ibreq->ibr_name);
00319               ibreq->ibr_name = NULL;
00320               /* If we hit the link limit, bail.  */
00321               if (__builtin_expect (count_links > NIS_MAXLINKS, 0))
00322                 {
00323                   NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
00324                   ++done;
00325                   break;
00326                 }
00327               ++count_links;
00328               ibreq->ibr_name =
00329                 strdup (NIS_RES_OBJECT (res)->LI_data.li_name);
00330               if (ibreq->ibr_name == NULL)
00331                 {
00332                   NIS_RES_STATUS (res) = NIS_NOMEMORY;
00333                 fail:
00334                   __nisbind_destroy (&bptr);
00335                   nis_free_directory (dir);
00336                 fail3:
00337                   free (tablepath);
00338                   if (cb)
00339                     {
00340                      __nis_destroy_callback (cb);
00341                      ibreq->ibr_cbhost.ibr_cbhost_len = 0;
00342                      ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
00343                     }
00344                   if (names != namebuf)
00345                     nis_freenames (names);
00346                   nis_free_request (ibreq);
00347                   nis_freeresult (allres);
00348                   return res;
00349                 }
00350               if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len)
00351                 if (ibreq->ibr_srch.ibr_srch_len == 0)
00352                   {
00353                     ibreq->ibr_srch.ibr_srch_len =
00354                      NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len;
00355                     ibreq->ibr_srch.ibr_srch_val =
00356                      NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val;
00357                   }
00358               /* The following is a non-obvious optimization.  A
00359                  nis_freeresult call would call xdr_free as the
00360                  following code.  But it also would unnecessarily
00361                  free the result structure.  We avoid this here
00362                  along with the necessary tests.  */
00363               xdr_free ((xdrproc_t) _xdr_nis_result, (char *)res);
00364               memset (res, '\0', sizeof (*res));
00365               first_try = 1; /* Try at first the old binding */
00366               goto again;
00367              }
00368            else if ((flags & FOLLOW_PATH)
00369                    && NIS_RES_STATUS (res) == NIS_PARTIAL)
00370              {
00371               clnt_status = __follow_path (&tablepath, &tableptr, ibreq,
00372                                         &bptr);
00373               if (clnt_status != NIS_SUCCESS)
00374                 {
00375                   if (clnt_status == NIS_NOMEMORY)
00376                     NIS_RES_STATUS (res) = clnt_status;
00377                   ++done;
00378                 }
00379               else
00380                 {
00381                   /* The following is a non-obvious optimization.  A
00382                      nis_freeresult call would call xdr_free as the
00383                      following code.  But it also would unnecessarily
00384                      free the result structure.  We avoid this here
00385                      along with the necessary tests.  */
00386                   xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
00387                   memset (res, '\0', sizeof (*res));
00388                   first_try = 1;
00389                   goto again;
00390                 }
00391              }
00392            else if ((flags & (FOLLOW_PATH | ALL_RESULTS))
00393                    == (FOLLOW_PATH | ALL_RESULTS))
00394              {
00395               if (allres == NULL)
00396                 {
00397                   allres = res;
00398                   res = malloc (sizeof (nis_result));
00399                   if (res == NULL)
00400                     {
00401                      res = allres;
00402                      allres = NULL;
00403                      NIS_RES_STATUS (res) = NIS_NOMEMORY;
00404                      goto fail;
00405                     }
00406                   NIS_RES_STATUS (res) = NIS_RES_STATUS (allres);
00407                 }
00408               else
00409                 {
00410                   nis_object *objects_val
00411                     = realloc (NIS_RES_OBJECT (allres),
00412                              (NIS_RES_NUMOBJ (allres)
00413                               + NIS_RES_NUMOBJ (res))
00414                              * sizeof (nis_object));
00415                   if (objects_val == NULL)
00416                     {
00417                      NIS_RES_STATUS (res) = NIS_NOMEMORY;
00418                      goto fail;
00419                     }
00420                   NIS_RES_OBJECT (allres) = objects_val;
00421                   memcpy (NIS_RES_OBJECT (allres) + NIS_RES_NUMOBJ (allres),
00422                          NIS_RES_OBJECT (res),
00423                          NIS_RES_NUMOBJ (res) * sizeof (nis_object));
00424                   NIS_RES_NUMOBJ (allres) += NIS_RES_NUMOBJ (res);
00425                   NIS_RES_NUMOBJ (res) = 0;
00426                   free (NIS_RES_OBJECT (res));
00427                   NIS_RES_OBJECT (res) = NULL;
00428                   NIS_RES_STATUS (allres) = NIS_RES_STATUS (res);
00429                   xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
00430                 }
00431               clnt_status = __follow_path (&tablepath, &tableptr, ibreq,
00432                                         &bptr);
00433               if (clnt_status != NIS_SUCCESS)
00434                 {
00435                   /* Prepare for the nis_freeresult call.  */
00436                   memset (res, '\0', sizeof (*res));
00437 
00438                   if (clnt_status == NIS_NOMEMORY)
00439                     NIS_RES_STATUS (allres) = clnt_status;
00440                   ++done;
00441                 }
00442              }
00443            else
00444              ++done;
00445            break;
00446          case NIS_CBRESULTS:
00447            if (cb != NULL)
00448              {
00449               __nis_do_callback (&bptr, &res->cookie, cb);
00450               NIS_RES_STATUS (res) = cb->result;
00451 
00452               if (!(flags & ALL_RESULTS))
00453                 ++done;
00454               else
00455                 {
00456                   clnt_status
00457                     = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
00458                   if (clnt_status != NIS_SUCCESS)
00459                     {
00460                      if (clnt_status == NIS_NOMEMORY)
00461                        NIS_RES_STATUS (res) = clnt_status;
00462                      ++done;
00463                     }
00464                 }
00465              }
00466            break;
00467          case NIS_SYSTEMERROR:
00468          case NIS_NOSUCHNAME:
00469          case NIS_NOT_ME:
00470            /* If we had first tried the old binding, do nothing, but
00471               get a new binding */
00472            if (!first_try)
00473              {
00474               if (__nisbind_next (&bptr) != NIS_SUCCESS)
00475                 {
00476                   ++done;
00477                   break; /* No more servers to search */
00478                 }
00479               while (__nisbind_connect (&bptr) != NIS_SUCCESS)
00480                 {
00481                   if (__nisbind_next (&bptr) != NIS_SUCCESS)
00482                     {
00483                      ++done;
00484                      break; /* No more servers to search */
00485                     }
00486                 }
00487               goto again;
00488              }
00489            break;
00490          default:
00491            if (!first_try)
00492              {
00493               /* Try the next domainname if we don't follow a link.  */
00494               free (ibreq->ibr_name);
00495               ibreq->ibr_name = NULL;
00496               if (__builtin_expect (count_links, 0))
00497                 {
00498                   NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
00499                   ++done;
00500                   break;
00501                 }
00502               ++name_nr;
00503               if (names[name_nr] == NULL)
00504                 {
00505                   ++done;
00506                   break;
00507                 }
00508               ibreq->ibr_name = strdup (names[name_nr]);
00509               if (ibreq->ibr_name == NULL)
00510                 {
00511                   NIS_RES_STATUS (res) = NIS_NOMEMORY;
00512                   goto fail;
00513                 }
00514               first_try = 1; /* Try old binding at first */
00515               goto again;
00516              }
00517            break;
00518          }
00519       first_try = 0;
00520 
00521       if (cb)
00522        {
00523          __nis_destroy_callback (cb);
00524          ibreq->ibr_cbhost.ibr_cbhost_len = 0;
00525          ibreq->ibr_cbhost.ibr_cbhost_val = NULL;
00526          cb = NULL;
00527        }
00528 
00529       __nisbind_destroy (&bptr);
00530       nis_free_directory (dir);
00531     }
00532 
00533   free (tablepath);
00534 
00535   if (names != namebuf)
00536     nis_freenames (names);
00537 
00538   nis_free_request (ibreq);
00539 
00540   if (allres)
00541     {
00542       nis_freeresult (res);
00543       return allres;
00544     }
00545 
00546   return res;
00547 }
00548 libnsl_hidden_def (nis_list)
00549 
00550 nis_result *
00551 nis_add_entry (const_nis_name name, const nis_object *obj2, unsigned int flags)
00552 {
00553   nis_result *res = calloc (1, sizeof (nis_result));
00554   if (res == NULL)
00555     return NULL;
00556 
00557   if (name == NULL)
00558     {
00559       NIS_RES_STATUS (res) = NIS_BADNAME;
00560       return res;
00561     }
00562 
00563   ib_request *ibreq = __create_ib_request (name, flags);
00564   if (ibreq == NULL)
00565     {
00566       NIS_RES_STATUS (res) = NIS_BADNAME;
00567       return res;
00568     }
00569 
00570   nis_object obj;
00571   memcpy (&obj, obj2, sizeof (nis_object));
00572 
00573   size_t namelen = strlen (name);
00574   char buf1[namelen + 20];
00575   char buf4[namelen + 20];
00576 
00577   if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
00578     obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
00579 
00580   if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
00581     obj.zo_owner = nis_local_principal ();
00582 
00583   if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
00584     obj.zo_group = nis_local_group ();
00585 
00586   obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
00587 
00588   ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
00589   if (ibreq->ibr_obj.ibr_obj_val == NULL)
00590     {
00591       nis_free_request (ibreq);
00592       NIS_RES_STATUS (res) = NIS_NOMEMORY;
00593       return res;
00594     }
00595   ibreq->ibr_obj.ibr_obj_len = 1;
00596 
00597   nis_error status = __do_niscall (ibreq->ibr_name, NIS_IBADD,
00598                                (xdrproc_t) _xdr_ib_request,
00599                                (caddr_t) ibreq,
00600                                (xdrproc_t) _xdr_nis_result,
00601                                (caddr_t) res, 0, NULL);
00602   if (__builtin_expect (status != NIS_SUCCESS, 0))
00603     NIS_RES_STATUS (res) = status;
00604 
00605   nis_free_request (ibreq);
00606 
00607   return res;
00608 }
00609 
00610 nis_result *
00611 nis_modify_entry (const_nis_name name, const nis_object *obj2,
00612                 unsigned int flags)
00613 {
00614   nis_object obj;
00615   nis_result *res;
00616   nis_error status;
00617   ib_request *ibreq;
00618   size_t namelen = strlen (name);
00619   char buf1[namelen + 20];
00620   char buf4[namelen + 20];
00621 
00622   res = calloc (1, sizeof (nis_result));
00623   if (res == NULL)
00624     return NULL;
00625 
00626   ibreq = __create_ib_request (name, flags);
00627   if (ibreq == NULL)
00628     {
00629       NIS_RES_STATUS (res) = NIS_BADNAME;
00630       return res;
00631     }
00632 
00633   memcpy (&obj, obj2, sizeof (nis_object));
00634 
00635   if (obj.zo_name == NULL || strlen (obj.zo_name) == 0)
00636     obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1));
00637 
00638   if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0)
00639     obj.zo_owner = nis_local_principal ();
00640 
00641   if (obj.zo_group == NULL || strlen (obj.zo_group) == 0)
00642     obj.zo_group = nis_local_group ();
00643 
00644   obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4));
00645 
00646   ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL);
00647   if (ibreq->ibr_obj.ibr_obj_val == NULL)
00648     {
00649       nis_free_request (ibreq);
00650       NIS_RES_STATUS (res) = NIS_NOMEMORY;
00651       return res;
00652     }
00653   ibreq->ibr_obj.ibr_obj_len = 1;
00654 
00655   status = __do_niscall (ibreq->ibr_name, NIS_IBMODIFY,
00656                       (xdrproc_t) _xdr_ib_request,
00657                       (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
00658                       (caddr_t) res, 0, NULL);
00659   if (__builtin_expect (status != NIS_SUCCESS, 0))
00660     NIS_RES_STATUS (res) = status;
00661 
00662   nis_free_request (ibreq);
00663 
00664   return res;
00665 }
00666 
00667 nis_result *
00668 nis_remove_entry (const_nis_name name, const nis_object *obj,
00669                 unsigned int flags)
00670 {
00671   nis_result *res;
00672   ib_request *ibreq;
00673   nis_error status;
00674 
00675   res = calloc (1, sizeof (nis_result));
00676   if (res == NULL)
00677     return NULL;
00678 
00679   if (name == NULL)
00680     {
00681       NIS_RES_STATUS (res) = NIS_BADNAME;
00682       return res;
00683     }
00684 
00685   ibreq = __create_ib_request (name, flags);
00686   if (ibreq == NULL)
00687     {
00688       NIS_RES_STATUS (res) = NIS_BADNAME;
00689       return res;
00690     }
00691 
00692   if (obj != NULL)
00693     {
00694       ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL);
00695       if (ibreq->ibr_obj.ibr_obj_val == NULL)
00696        {
00697          nis_free_request (ibreq);
00698          NIS_RES_STATUS (res) = NIS_NOMEMORY;
00699          return res;
00700        }
00701       ibreq->ibr_obj.ibr_obj_len = 1;
00702     }
00703 
00704   if ((status = __do_niscall (ibreq->ibr_name, NIS_IBREMOVE,
00705                            (xdrproc_t) _xdr_ib_request,
00706                            (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
00707                            (caddr_t) res, 0, NULL)) != NIS_SUCCESS)
00708     NIS_RES_STATUS (res) = status;
00709 
00710   nis_free_request (ibreq);
00711 
00712   return res;
00713 }
00714 
00715 nis_result *
00716 nis_first_entry (const_nis_name name)
00717 {
00718   nis_result *res;
00719   ib_request *ibreq;
00720   nis_error status;
00721 
00722   res = calloc (1, sizeof (nis_result));
00723   if (res == NULL)
00724     return NULL;
00725 
00726   if (name == NULL)
00727     {
00728       NIS_RES_STATUS (res) = NIS_BADNAME;
00729       return res;
00730     }
00731 
00732   ibreq = __create_ib_request (name, 0);
00733   if (ibreq == NULL)
00734     {
00735       NIS_RES_STATUS (res) = NIS_BADNAME;
00736       return res;
00737     }
00738 
00739   status = __do_niscall (ibreq->ibr_name, NIS_IBFIRST,
00740                       (xdrproc_t) _xdr_ib_request,
00741                       (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
00742                       (caddr_t) res, 0, NULL);
00743 
00744   if (__builtin_expect (status != NIS_SUCCESS, 0))
00745     NIS_RES_STATUS (res) = status;
00746 
00747   nis_free_request (ibreq);
00748 
00749   return res;
00750 }
00751 
00752 nis_result *
00753 nis_next_entry (const_nis_name name, const netobj *cookie)
00754 {
00755   nis_result *res;
00756   ib_request *ibreq;
00757   nis_error status;
00758 
00759   res = calloc (1, sizeof (nis_result));
00760   if (res == NULL)
00761     return NULL;
00762 
00763   if (name == NULL)
00764     {
00765       NIS_RES_STATUS (res) = NIS_BADNAME;
00766       return res;
00767     }
00768 
00769   ibreq = __create_ib_request (name, 0);
00770   if (ibreq == NULL)
00771     {
00772       NIS_RES_STATUS (res) = NIS_BADNAME;
00773       return res;
00774     }
00775 
00776   if (cookie != NULL)
00777     {
00778       ibreq->ibr_cookie.n_bytes = cookie->n_bytes;
00779       ibreq->ibr_cookie.n_len = cookie->n_len;
00780     }
00781 
00782   status = __do_niscall (ibreq->ibr_name, NIS_IBNEXT,
00783                       (xdrproc_t) _xdr_ib_request,
00784                       (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result,
00785                       (caddr_t) res, 0, NULL);
00786 
00787   if (__builtin_expect (status != NIS_SUCCESS, 0))
00788     NIS_RES_STATUS (res) = status;
00789 
00790   if (cookie != NULL)
00791     {
00792       /* Don't give cookie free, it is not from us */
00793       ibreq->ibr_cookie.n_bytes = NULL;
00794       ibreq->ibr_cookie.n_len = 0;
00795     }
00796 
00797   nis_free_request (ibreq);
00798 
00799   return res;
00800 }