(linenum→info "unix/slp.c:2238")

glibc/2.7/nis/nis_lookup.c

    1: /* Copyright (C) 1997-1999, 2004, 2005, 2006, 2007
    2:    Free Software Foundation, Inc.
    3:    This file is part of the GNU C Library.
    4:    Contributed by Thorsten Kukuk <kukuk@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 Lesser General Public
    8:    License as published by the Free Software Foundation; either
    9:    version 2.1 of the 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:    Lesser General Public License for more details.
   15: 
   16:    You should have received a copy of the GNU Lesser General Public
   17:    License along with the GNU C Library; if not, write to the Free
   18:    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   19:    02111-1307 USA.  */
   20: 
   21: #include <string.h>
   22: #include <rpcsvc/nis.h>
   23: #include "nis_xdr.h"
   24: #include "nis_intern.h"
   25: #include <libnsl.h>
   26: 
   27: 
   28: nis_result *
   29: nis_lookup (const_nis_name name, const unsigned int flags)
   30: {
   31:   nis_result *res = calloc (1, sizeof (nis_result));
   32:   struct ns_request req;
   33:   nis_name *names;
   34:   nis_error status;
   35:   int link_first_try = 0;
   36:   int count_links = 0;   /* We will follow only 16 links in the deep */
   37:   int done = 0;
   38:   int name_nr = 0;
   39:   nis_name namebuf[2] = {NULL, NULL};
   40: 
   41:   if (res == NULL)
   42:     return NULL;
   43: 
   44:   if ((flags & EXPAND_NAME) && (name[strlen (name) - 1] != '.'))
   45:     {
   46:       names = nis_getnames (name);
   47:       if (names == NULL)
   48:         {
   49:           NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
   50:           return res;
   51:         }
   52:     }
   53:   else
   54:     {
   55:       names = namebuf;
   56:       names[0] = (nis_name)name;
   57:     }
   58: 
   59:   req.ns_name = names[0];
   60:   while (!done)
   61:     {
   62:       dir_binding bptr;
   63:       directory_obj *dir = NULL;
   64:       req.ns_object.ns_object_len = 0;
   65:       req.ns_object.ns_object_val = NULL;
   66: 
   67:       status = __prepare_niscall (req.ns_name, &dir, &bptr, flags);
   68:       if (__builtin_expect (status != NIS_SUCCESS, 0))
   69:         {
   70:           NIS_RES_STATUS (res) = status;
   71:           goto out;
   72:         }
   73: 
   74:       do
   75:         {
   76:           static const struct timeval RPCTIMEOUT = {10, 0};
   77:           enum clnt_stat result;
   78: 
   79:         again:
   80:           result = clnt_call (bptr.clnt, NIS_LOOKUP,
   81:                               (xdrproc_t) _xdr_ns_request,
   82:                               (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
   83:                               (caddr_t) res, RPCTIMEOUT);
   84: 
   85:           if (result != RPC_SUCCESS)
   86:             status = NIS_RPCERROR;
   87:           else
   88:             {
   89:               status = NIS_SUCCESS;
   90: 
   91:               if (NIS_RES_STATUS (res) == NIS_SUCCESS)
   92:                 {
   93:                     if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
   94:                         && (flags & FOLLOW_LINKS)) /* We are following links */
   95:                       {
   96:                         /* if we hit the link limit, bail */
   97:                         if (count_links > NIS_MAXLINKS)
   98:                           {
   99:                             NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
  100:                             break;
  101:                           }
  102:                         ++count_links;
  103:                         req.ns_name =
  104:                           strdupa (NIS_RES_OBJECT (res)->LI_data.li_name);
  105: 
  106:                         /* The following is a non-obvious optimization.  A
  107:                            nis_freeresult call would call xdr_free as the
  108:                            following code.  But it also would unnecessarily
  109:                            free the result structure.  We avoid this here
  110:                            along with the necessary tests.  */
  111:                         xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
  112:                         memset (res, '\0', sizeof (*res));
  113: 
  114:                         link_first_try = 1; /* Try at first the old binding */
  115:                         goto again;
  116:                       }
  117:                 }
  118:               else
  119:                 if (NIS_RES_STATUS (res) == NIS_SYSTEMERROR
  120:                     || NIS_RES_STATUS (res) == NIS_NOSUCHNAME
  121:                     || NIS_RES_STATUS (res) == NIS_NOT_ME)
  122:                   {
  123:                     if (link_first_try)
  124:                       {
  125:                         __nisbind_destroy (&bptr);
  126:                         nis_free_directory (dir);
  127:                         /* Otherwise __nisfind_server will not do anything.  */
  128:                         dir = NULL;
  129: 
  130:                         if (__nisfind_server (req.ns_name, 1, &dir, &bptr,
  131:                                               flags & ~MASTER_ONLY)
  132:                             != NIS_SUCCESS)
  133:                           goto out;
  134:                       }
  135:                     else
  136:                       if (__nisbind_next (&bptr) != NIS_SUCCESS)
  137:                         {
  138:                           /* No more servers to search.  Try parent.  */
  139:                           const char *ndomain = __nis_domain_of (req.ns_name);
  140:                           req.ns_name = strdupa (ndomain);
  141:                           if (strcmp (req.ns_name, ".") == 0)
  142:                             {
  143:                               NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
  144:                               goto out;
  145:                             }
  146: 
  147:                           __nisbind_destroy (&bptr);
  148:                           nis_free_directory (dir);
  149:                           dir = NULL;
  150:                           status = __prepare_niscall (req.ns_name, &dir,
  151:                                                       &bptr, flags);
  152:                           if (__builtin_expect (status != NIS_SUCCESS, 0))
  153:                             {
  154:                               NIS_RES_STATUS (res) = status;
  155:                               goto out;
  156:                             }
  157:                           goto again;
  158:                         }
  159: 
  160:                     while (__nisbind_connect (&bptr) != NIS_SUCCESS)
  161:                       {
  162:                         if (__nisbind_next (&bptr) != NIS_SUCCESS)
  163:                           {
  164:                             nis_free_directory (dir);
  165:                             goto out;
  166:                           }
  167:                       }
  168:                     goto again;
  169:                   }
  170:               break;
  171:             }
  172:           link_first_try = 0; /* Set it back */
  173:         }
  174:       while ((flags & HARD_LOOKUP) && status == NIS_RPCERROR);
  175: 
  176:       __nisbind_destroy (&bptr);
  177:       nis_free_directory (dir);
  178: 
  179:       if (status != NIS_SUCCESS)
  180:         {
  181:           NIS_RES_STATUS (res) = status;
  182:           goto out;
  183:         }
  184: 
  185:       switch (NIS_RES_STATUS (res))
  186:         {
  187:         case NIS_PARTIAL:
  188:         case NIS_SUCCESS:
  189:         case NIS_S_SUCCESS:
  190:         case NIS_LINKNAMEERROR: /* We follow to max links */
  191:         case NIS_UNAVAIL: /* NIS+ is not installed, or all servers are down */
  192:           ++done;
  193:           break;
  194:         default:
  195:           /* Try the next domainname if we don't follow a link */
  196:           if (count_links)
  197:             {
  198:               free (req.ns_name);
  199:               NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
  200:               ++done;
  201:               break;
  202:             }
  203:           ++name_nr;
  204:           if (names[name_nr] == NULL)
  205:             {
  206:               ++done;
  207:               break;
  208:             }
  209:           req.ns_name = names[name_nr];
  210:           break;
  211:         }
  212:     }
  213: 
  214:  out:
  215:   if (names != namebuf)
  216:     nis_freenames (names);
  217: 
  218:   return res;
  219: }
  220: libnsl_hidden_def (nis_lookup)
Syntax (Markdown)