Back to index

glibc  2.9
nis_subr.c
Go to the documentation of this file.
00001 /* Copyright (c) 1997,1999,2000,2004,2005,2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <string.h>
00022 #include <rpcsvc/nis.h>
00023 
00024 nis_name
00025 nis_leaf_of (const_nis_name name)
00026 {
00027   static char result[NIS_MAXNAMELEN + 1];
00028 
00029   return nis_leaf_of_r (name, result, NIS_MAXNAMELEN);
00030 }
00031 
00032 nis_name
00033 nis_leaf_of_r (const_nis_name name, char *buffer, size_t buflen)
00034 {
00035   size_t i = 0;
00036 
00037   buffer[0] = '\0';
00038 
00039   while (name[i] != '.' && name[i] != '\0')
00040     i++;
00041 
00042   if (__builtin_expect (i >= buflen, 0))
00043     {
00044       __set_errno (ERANGE);
00045       return NULL;
00046     }
00047 
00048   *((char *) __mempcpy (buffer, name, i)) = '\0';
00049 
00050   return buffer;
00051 }
00052 libnsl_hidden_def (nis_leaf_of_r)
00053 
00054 nis_name
00055 nis_name_of (const_nis_name name)
00056 {
00057   static char result[NIS_MAXNAMELEN + 1];
00058 
00059   return nis_name_of_r (name, result, NIS_MAXNAMELEN);
00060 }
00061 
00062 nis_name
00063 nis_name_of_r (const_nis_name name, char *buffer, size_t buflen)
00064 {
00065   char *local_domain;
00066   int diff;
00067 
00068   local_domain = nis_local_directory ();
00069 
00070   diff = strlen (name) - strlen (local_domain);
00071   if (diff <= 0)
00072     return NULL;
00073 
00074   if (strcmp (&name[diff], local_domain) != 0)
00075     return NULL;
00076 
00077   if ((size_t) diff >= buflen)
00078     {
00079       __set_errno (ERANGE);
00080       return NULL;
00081     }
00082 
00083   *((char *) __mempcpy (buffer, name, diff - 1)) = '\0';
00084 
00085   if (diff - 1 == 0)
00086     return NULL;
00087 
00088   return buffer;
00089 }
00090 libnsl_hidden_def (nis_name_of_r)
00091 
00092 static int __always_inline
00093 count_dots (const_nis_name str)
00094 {
00095   int count = 0;
00096 
00097   for (size_t i = 0; str[i] != '\0'; ++i)
00098     if (str[i] == '.')
00099       ++count;
00100 
00101   return count;
00102 }
00103 
00104 /* If we run out of memory, we don't give already allocated memory
00105    free. The overhead for bringing getnames back in a safe state to
00106    free it is to big. */
00107 nis_name *
00108 nis_getnames (const_nis_name name)
00109 {
00110   const char *local_domain = nis_local_directory ();
00111   size_t local_domain_len = strlen (local_domain);
00112   size_t name_len = strlen (name);
00113   char *path;
00114   int pos = 0;
00115   char *saveptr = NULL;
00116   int have_point;
00117   const char *cp;
00118   const char *cp2;
00119 
00120   int count = 2;
00121   nis_name *getnames = malloc ((count + 1) * sizeof (char *));
00122   if (__builtin_expect (getnames == NULL, 0))
00123       return NULL;
00124 
00125   /* Do we have a fully qualified NIS+ name ? If yes, give it back */
00126   if (name[name_len - 1] == '.')
00127     {
00128       if ((getnames[0] = strdup (name)) == NULL)
00129        {
00130        free_null:
00131          while (pos-- > 0)
00132            free (getnames[pos]);
00133          free (getnames);
00134          return NULL;
00135        }
00136 
00137       getnames[1] = NULL;
00138 
00139       return getnames;
00140     }
00141 
00142   /* If the passed NAME is shared a suffix (the latter of course with
00143      a final dot) with each other we pass back NAME with a final
00144      dot.  */
00145   if (local_domain_len > 2)
00146     {
00147       have_point = 0;
00148       cp = &local_domain[local_domain_len - 2];
00149       cp2 = &name[name_len - 1];
00150 
00151       while (*cp == *cp2)
00152        {
00153          if (*cp == '.')
00154            have_point = 1;
00155          --cp;
00156          --cp2;
00157          if (cp < local_domain)
00158            {
00159              have_point = cp2 < name || *cp2 == '.';
00160              break;
00161            }
00162          if (cp2 < name)
00163            {
00164              have_point = *cp == '.';
00165              break;
00166            }
00167        }
00168 
00169       if (have_point)
00170        {
00171          getnames[0] = malloc (name_len + 2);
00172          if (getnames[0] == NULL)
00173            goto free_null;
00174 
00175          strcpy (stpcpy (getnames[0], name), ".");
00176          ++pos;
00177        }
00178     }
00179 
00180   /* Get the search path, where we have to search "name" */
00181   path = getenv ("NIS_PATH");
00182   if (path == NULL)
00183     path = strdupa ("$");
00184   else
00185     path = strdupa (path);
00186 
00187   have_point = strchr (name, '.') != NULL;
00188 
00189   cp = __strtok_r (path, ":", &saveptr);
00190   while (cp)
00191     {
00192       if (strcmp (cp, "$") == 0)
00193        {
00194          const char *cptr = local_domain;
00195          char *tmp;
00196 
00197          while (*cptr != '\0' && count_dots (cptr) >= 2)
00198            {
00199              if (pos >= count)
00200               {
00201                 count += 5;
00202                 nis_name *newp = realloc (getnames,
00203                                        (count + 1) * sizeof (char *));
00204                 if (__builtin_expect (newp == NULL, 0))
00205                   goto free_null;
00206                 getnames = newp;
00207               }
00208              tmp = malloc (strlen (cptr) + local_domain_len + name_len + 2);
00209              if (__builtin_expect (tmp == NULL, 0))
00210               goto free_null;
00211 
00212              getnames[pos] = tmp;
00213              tmp = stpcpy (tmp, name);
00214              *tmp++ = '.';
00215              if (cptr[1] != '\0')
00216               stpcpy (tmp, cptr);
00217              else
00218               ++cptr;
00219 
00220              ++pos;
00221 
00222              while (*cptr != '.' && *cptr != '\0')
00223               ++cptr;
00224              if (cptr[0] != '\0' && cptr[1] != '\0')
00225               /* If we have only ".", don't remove the "." */
00226               ++cptr;
00227            }
00228        }
00229       else
00230        {
00231          char *tmp;
00232          size_t cplen = strlen (cp);
00233 
00234          if (cp[cplen - 1] == '$')
00235            {
00236              char *p;
00237 
00238              tmp = malloc (cplen + local_domain_len + name_len + 2);
00239              if (__builtin_expect (tmp == NULL, 0))
00240               goto free_null;
00241 
00242              p = __stpcpy (tmp, name);
00243              *p++ = '.';
00244              p = __mempcpy (p, cp, cplen);
00245              --p;
00246              if (p[-1] != '.')
00247               *p++ = '.';
00248              __stpcpy (p, local_domain);
00249            }
00250          else
00251            {
00252              char *p;
00253 
00254              tmp = malloc (cplen + name_len + 3);
00255              if (__builtin_expect (tmp == NULL, 0))
00256               goto free_null;
00257 
00258              p = __mempcpy (tmp, name, name_len);
00259              *p++ = '.';
00260              p = __mempcpy (p, cp, cplen);
00261              if (p[-1] != '.')
00262               *p++ = '.';
00263              *p = '\0';
00264            }
00265 
00266          if (pos >= count)
00267            {
00268              count += 5;
00269              nis_name *newp = realloc (getnames,
00270                                    (count + 1) * sizeof (char *));
00271              if (__builtin_expect (newp == NULL, 0))
00272               goto free_null;
00273              getnames = newp;
00274            }
00275          getnames[pos] = tmp;
00276          ++pos;
00277        }
00278       cp = __strtok_r (NULL, ":", &saveptr);
00279     }
00280 
00281   if (pos == 0
00282       && __asprintf (&getnames[pos++], "%s%s%s%s",
00283                    name, name[name_len - 1] == '.' ? "" : ".",
00284                    local_domain,
00285                    local_domain[local_domain_len - 1] == '.' ? "" : ".") < 0)
00286     goto free_null;
00287 
00288   getnames[pos] = NULL;
00289 
00290   return getnames;
00291 }
00292 libnsl_hidden_def (nis_getnames)
00293 
00294 void
00295 nis_freenames (nis_name *names)
00296 {
00297   int i = 0;
00298 
00299   while (names[i] != NULL)
00300     {
00301       free (names[i]);
00302       ++i;
00303     }
00304 
00305   free (names);
00306 }
00307 libnsl_hidden_def  (nis_freenames)
00308 
00309 name_pos
00310 nis_dir_cmp (const_nis_name n1, const_nis_name n2)
00311 {
00312   int len1, len2;
00313 
00314   len1 = strlen (n1);
00315   len2 = strlen (n2);
00316 
00317   if (len1 == len2)
00318     {
00319       if (strcmp (n1, n2) == 0)
00320        return SAME_NAME;
00321       else
00322        return NOT_SEQUENTIAL;
00323     }
00324 
00325   if (len1 < len2)
00326     {
00327       if (n2[len2 - len1 - 1] != '.')
00328        return NOT_SEQUENTIAL;
00329       else if (strcmp (&n2[len2 - len1], n1) == 0)
00330        return HIGHER_NAME;
00331       else
00332        return NOT_SEQUENTIAL;
00333     }
00334   else
00335     {
00336       if (n1[len1 - len2 - 1] != '.')
00337        return NOT_SEQUENTIAL;
00338       else if (strcmp (&n1[len1 - len2], n2) == 0)
00339        return LOWER_NAME;
00340       else
00341        return NOT_SEQUENTIAL;
00342 
00343     }
00344 }
00345 libnsl_hidden_def (nis_dir_cmp)
00346 
00347 void
00348 nis_destroy_object (nis_object *obj)
00349 {
00350   nis_free_object (obj);
00351 }
00352 libnsl_hidden_def (nis_destroy_object)