Back to index

glibc  2.9
nis-grp.c
Go to the documentation of this file.
00001 /* Copyright (C) 1996-1999, 2001-2004, 2006 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
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 <ctype.h>
00021 #include <errno.h>
00022 #include <grp.h>
00023 #include <nss.h>
00024 #include <string.h>
00025 #include <bits/libc-lock.h>
00026 #include <rpcsvc/yp.h>
00027 #include <rpcsvc/ypclnt.h>
00028 
00029 #include "nss-nis.h"
00030 #include <libnsl.h>
00031 
00032 /* Get the declaration of the parser function.  */
00033 #define ENTNAME grent
00034 #define STRUCTURE group
00035 #define EXTERN_PARSER
00036 #include <nss/nss_files/files-parse.c>
00037 
00038 /* Protect global state against multiple changers */
00039 __libc_lock_define_initialized (static, lock)
00040 
00041 static bool_t new_start = 1;
00042 static char *oldkey;
00043 static int oldkeylen;
00044 static intern_t intern;
00045 
00046 
00047 static void
00048 internal_nis_endgrent (void)
00049 {
00050   new_start = 1;
00051   if (oldkey != NULL)
00052     {
00053       free (oldkey);
00054       oldkey = NULL;
00055       oldkeylen = 0;
00056     }
00057 
00058   struct response_t *curr = intern.next;
00059 
00060   while (curr != NULL)
00061     {
00062       struct response_t *last = curr;
00063       curr = curr->next;
00064       free (last);
00065     }
00066 
00067   intern.next = intern.start = NULL;
00068 }
00069 
00070 
00071 enum nss_status
00072 _nss_nis_endgrent (void)
00073 {
00074   __libc_lock_lock (lock);
00075 
00076   internal_nis_endgrent ();
00077 
00078   __libc_lock_unlock (lock);
00079 
00080   return NSS_STATUS_SUCCESS;
00081 }
00082 
00083 
00084 enum nss_status
00085 internal_nis_setgrent (void)
00086 {
00087   /* We have to read all the data now.  */
00088   char *domain;
00089   if (__builtin_expect (yp_get_default_domain (&domain), 0))
00090     return NSS_STATUS_UNAVAIL;
00091 
00092   struct ypall_callback ypcb;
00093 
00094   ypcb.foreach = _nis_saveit;
00095   ypcb.data = (char *) &intern;
00096   enum nss_status status = yperr2nss (yp_all (domain, "group.byname", &ypcb));
00097 
00098 
00099   /* Mark the last buffer as full.  */
00100   if (intern.next != NULL)
00101     intern.next->size = intern.offset;
00102 
00103   intern.next = intern.start;
00104   intern.offset = 0;
00105 
00106   return status;
00107 }
00108 
00109 
00110 enum nss_status
00111 _nss_nis_setgrent (int stayopen)
00112 {
00113   enum nss_status result = NSS_STATUS_SUCCESS;
00114 
00115   __libc_lock_lock (lock);
00116 
00117   internal_nis_endgrent ();
00118 
00119   if (_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
00120     result = internal_nis_setgrent ();
00121 
00122   __libc_lock_unlock (lock);
00123 
00124   return result;
00125 }
00126 
00127 
00128 static enum nss_status
00129 internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen,
00130                       int *errnop)
00131 {
00132   /* If we read the entire database at setpwent time we just iterate
00133      over the data we have in memory.  */
00134   bool batch_read = intern.start != NULL;
00135 
00136   char *domain = NULL;
00137   if (!batch_read && __builtin_expect (yp_get_default_domain (&domain), 0))
00138     return NSS_STATUS_UNAVAIL;
00139 
00140   /* Get the next entry until we found a correct one. */
00141   int parse_res;
00142   do
00143     {
00144       char *result;
00145       char *outkey;
00146       int len;
00147       int keylen;
00148 
00149       if (batch_read)
00150        {
00151          struct response_t *bucket;
00152 
00153        handle_batch_read:
00154          bucket = intern.next;
00155 
00156          if (__builtin_expect (intern.offset >= bucket->size, 0))
00157            {
00158              if (bucket->next == NULL)
00159               return NSS_STATUS_NOTFOUND;
00160 
00161              /* We look at all the content in the current bucket.  Go on
00162                to the next.  */
00163              bucket = intern.next = bucket->next;
00164              intern.offset = 0;
00165            }
00166 
00167          for (result = &bucket->mem[intern.offset]; isspace (*result);
00168               ++result)
00169            ++intern.offset;
00170 
00171          len = strlen (result);
00172        }
00173       else
00174        {
00175          int yperr;
00176 
00177          if (new_start)
00178            {
00179              /* Maybe we should read the database in one piece.  */
00180              if ((_nsl_default_nss () & NSS_FLAG_SETENT_BATCH_READ)
00181                 && internal_nis_setgrent () == NSS_STATUS_SUCCESS
00182                 && intern.start != NULL)
00183               {
00184                 batch_read = true;
00185                 goto handle_batch_read;
00186               }
00187 
00188              yperr = yp_first (domain, "group.byname", &outkey, &keylen,
00189                             &result, &len);
00190            }
00191          else
00192            yperr = yp_next (domain, "group.byname", oldkey, oldkeylen,
00193                           &outkey, &keylen, &result, &len);
00194 
00195          if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
00196            {
00197              enum nss_status retval = yperr2nss (yperr);
00198 
00199              if (retval == NSS_STATUS_TRYAGAIN)
00200               *errnop = errno;
00201              return retval;
00202            }
00203        }
00204 
00205       if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
00206         {
00207           free (result);
00208           *errnop = ERANGE;
00209           return NSS_STATUS_TRYAGAIN;
00210         }
00211 
00212       char *p = strncpy (buffer, result, len);
00213       buffer[len] = '\0';
00214       while (isspace (*p))
00215         ++p;
00216       if (!batch_read)
00217        free (result);
00218 
00219       parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
00220                                      errnop);
00221       if (__builtin_expect (parse_res == -1, 0))
00222        {
00223          if (!batch_read)
00224            free (outkey);
00225          *errnop = ERANGE;
00226          return NSS_STATUS_TRYAGAIN;
00227        }
00228 
00229       if (batch_read)
00230        intern.offset += len + 1;
00231       else
00232        {
00233          free (oldkey);
00234          oldkey = outkey;
00235          oldkeylen = keylen;
00236          new_start = 0;
00237        }
00238     }
00239   while (parse_res < 1);
00240 
00241   return NSS_STATUS_SUCCESS;
00242 }
00243 
00244 enum nss_status
00245 _nss_nis_getgrent_r (struct group *result, char *buffer, size_t buflen,
00246                    int *errnop)
00247 {
00248   int status;
00249 
00250   __libc_lock_lock (lock);
00251 
00252   status = internal_nis_getgrent_r (result, buffer, buflen, errnop);
00253 
00254   __libc_lock_unlock (lock);
00255 
00256   return status;
00257 }
00258 
00259 enum nss_status
00260 _nss_nis_getgrnam_r (const char *name, struct group *grp,
00261                    char *buffer, size_t buflen, int *errnop)
00262 {
00263   if (name == NULL)
00264     {
00265       *errnop = EINVAL;
00266       return NSS_STATUS_UNAVAIL;
00267     }
00268 
00269   char *domain;
00270   if (__builtin_expect (yp_get_default_domain (&domain), 0))
00271     return NSS_STATUS_UNAVAIL;
00272 
00273   char *result;
00274   int len;
00275   int yperr = yp_match (domain, "group.byname", name, strlen (name), &result,
00276                      &len);
00277 
00278   if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
00279     {
00280       enum nss_status retval = yperr2nss (yperr);
00281 
00282       if (retval == NSS_STATUS_TRYAGAIN)
00283         *errnop = errno;
00284       return retval;
00285     }
00286 
00287   if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
00288     {
00289       free (result);
00290       *errnop = ERANGE;
00291       return NSS_STATUS_TRYAGAIN;
00292     }
00293 
00294   char *p = strncpy (buffer, result, len);
00295   buffer[len] = '\0';
00296   while (isspace (*p))
00297     ++p;
00298   free (result);
00299 
00300   int parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
00301                                      errnop);
00302   if (__builtin_expect  (parse_res < 1, 0))
00303     {
00304       if (parse_res == -1)
00305        return NSS_STATUS_TRYAGAIN;
00306       else
00307        return NSS_STATUS_NOTFOUND;
00308     }
00309   return NSS_STATUS_SUCCESS;
00310 }
00311 
00312 enum nss_status
00313 _nss_nis_getgrgid_r (gid_t gid, struct group *grp,
00314                    char *buffer, size_t buflen, int *errnop)
00315 {
00316   char *domain;
00317   if (__builtin_expect (yp_get_default_domain (&domain), 0))
00318     return NSS_STATUS_UNAVAIL;
00319 
00320   char buf[32];
00321   int nlen = sprintf (buf, "%lu", (unsigned long int) gid);
00322 
00323   char *result;
00324   int len;
00325   int yperr = yp_match (domain, "group.bygid", buf, nlen, &result, &len);
00326 
00327   if (__builtin_expect (yperr != YPERR_SUCCESS, 0))
00328     {
00329       enum nss_status retval = yperr2nss (yperr);
00330 
00331       if (retval == NSS_STATUS_TRYAGAIN)
00332         *errnop = errno;
00333       return retval;
00334     }
00335 
00336   if (__builtin_expect ((size_t) (len + 1) > buflen, 0))
00337     {
00338       free (result);
00339       *errnop = ERANGE;
00340       return NSS_STATUS_TRYAGAIN;
00341     }
00342 
00343   char *p = strncpy (buffer, result, len);
00344   buffer[len] = '\0';
00345   while (isspace (*p))
00346     ++p;
00347   free (result);
00348 
00349   int parse_res = _nss_files_parse_grent (p, grp, (void *) buffer, buflen,
00350                                      errnop);
00351   if (__builtin_expect (parse_res < 1, 0))
00352     {
00353       if (parse_res == -1)
00354        return NSS_STATUS_TRYAGAIN;
00355       else
00356        return NSS_STATUS_NOTFOUND;
00357     }
00358   return NSS_STATUS_SUCCESS;
00359 }