Back to index

glibc  2.9
db-alias.c
Go to the documentation of this file.
00001 /* Mail alias file parser in nss_db module.
00002    Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
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 <aliases.h>
00022 #include <alloca.h>
00023 #include <ctype.h>
00024 #include <dlfcn.h>
00025 #include <errno.h>
00026 #include <bits/libc-lock.h>
00027 #include <paths.h>
00028 #include <string.h>
00029 
00030 #include "nsswitch.h"
00031 #include "nss_db.h"
00032 
00033 /* Locks the static variables in this file.  */
00034 __libc_lock_define_initialized (static, lock)
00035 
00036 /* Maintenance of the shared handle open on the database.  */
00037 
00038 static NSS_DB *db;
00039 static int keep_db;
00040 static unsigned int entidx; /* Index for `getaliasent_r'. */
00041 
00042 
00043 /* Open database.  */
00044 enum nss_status
00045 _nss_db_setaliasent (int stayopen)
00046 {
00047   enum nss_status status;
00048 
00049   __libc_lock_lock (lock);
00050 
00051   status = internal_setent (_PATH_VARDB "aliases.db", &db);
00052 
00053   /* Remember STAYOPEN flag.  */
00054   if (db != NULL)
00055     keep_db |= stayopen;
00056 
00057   /* Reset the sequential index.  */
00058   entidx = 0;
00059 
00060   __libc_lock_unlock (lock);
00061 
00062   return status;
00063 }
00064 
00065 
00066 /* Close it again.  */
00067 enum nss_status
00068 _nss_db_endaliasent (void)
00069 {
00070   __libc_lock_lock (lock);
00071 
00072   internal_endent (&db);
00073 
00074   /* Reset STAYOPEN flag.  */
00075   keep_db = 0;
00076 
00077   __libc_lock_unlock (lock);
00078 
00079   return NSS_STATUS_SUCCESS;
00080 }
00081 
00082 /* We provide the parse function here.  The parser in libnss_files
00083    cannot be used.  The generation of the db file already resolved all
00084    :include: statements so we simply have to parse the list and store
00085    the result.  */
00086 static enum nss_status
00087 lookup (DBT *key, struct aliasent *result, char *buffer,
00088        size_t buflen, int *errnop)
00089 {
00090   enum nss_status status;
00091   DBT value;
00092 
00093   /* Open the database.  */
00094   if (db == NULL)
00095     {
00096       status = internal_setent (_PATH_VARDB "aliases.db", &db);
00097       if (status != NSS_STATUS_SUCCESS)
00098        {
00099          *errnop = errno;
00100          return status;
00101        }
00102     }
00103 
00104   value.flags = 0;
00105   if (DL_CALL_FCT (db->get, (db->db, NULL, key, &value, 0)) == 0)
00106     {
00107       const char *src = value.data;
00108       char *cp;
00109       size_t cnt;
00110 
00111       result->alias_members_len = 0;
00112 
00113       /* We now have to fill the BUFFER with all the information. */
00114       if (buflen < key->size + 1)
00115        {
00116        no_more_room:
00117          *errnop = ERANGE;
00118          return NSS_STATUS_TRYAGAIN;
00119        }
00120 
00121       buffer = stpncpy (buffer, key->data, key->size) + 1;
00122       buflen -= key->size + 1;
00123 
00124       while (*src != '\0')
00125        {
00126          const char *end, *upto;
00127          while (isspace (*src))
00128            ++src;
00129 
00130          end = strchr (src, ',');
00131          if (end == NULL)
00132            end = strchr (src, '\0');
00133          for (upto = end; upto > src && isspace (upto[-1]); --upto);
00134 
00135          if (upto != src)
00136            {
00137              if ((upto - src) + __alignof__ (char *) > buflen)
00138               goto no_more_room;
00139              buffer = stpncpy (buffer, src, upto - src) + 1;
00140              buflen -= (upto - src) + __alignof (char *);
00141              ++result->alias_members_len;
00142            }
00143          src = end + (*end != '\0');
00144        }
00145 
00146       /* Now prepare the return.  Provide string pointers for the
00147         currently selected aliases.  */
00148 
00149       /* Adjust the pointer so it is aligned for storing pointers.  */
00150       buffer += __alignof__ (char *) - 1;
00151       buffer -= ((buffer - (char *) 0) % __alignof__ (char *));
00152       result->alias_members = (char **) buffer;
00153 
00154       /* Compute addresses of alias entry strings.  */
00155       cp = result->alias_name;
00156       for (cnt = 0; cnt < result->alias_members_len; ++cnt)
00157        {
00158          cp = strchr (cp, '\0') + 1;
00159          result->alias_members[cnt] = cp;
00160        }
00161 
00162       status = (result->alias_members_len == 0
00163               ? NSS_STATUS_RETURN : NSS_STATUS_SUCCESS);
00164     }
00165   else
00166     status = NSS_STATUS_NOTFOUND;
00167 
00168   if (! keep_db)
00169     internal_endent (&db);
00170 
00171   return status;
00172 }
00173 
00174 enum nss_status
00175 _nss_db_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen,
00176                      int *errnop)
00177 {
00178   /* Return next entry in alias file.  */
00179   enum nss_status status;
00180   char buf[20];
00181   DBT key;
00182 
00183   __libc_lock_lock (lock);
00184   key.size = snprintf (key.data = buf, sizeof buf, "0%u", entidx++);
00185   key.flags = 0;
00186   status = lookup (&key, result, buffer, buflen, errnop);
00187   if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
00188     /* Give the user a chance to get the same entry with a larger buffer.  */
00189     --entidx;
00190   __libc_lock_unlock (lock);
00191 
00192   return status;
00193 }
00194 
00195 
00196 enum nss_status
00197 _nss_db_getaliasbyname_r (const char *name, struct aliasent *result,
00198                        char *buffer, size_t buflen, int *errnop)
00199 {
00200   DBT key;
00201   enum nss_status status;
00202 
00203   key.size = 1 + strlen (name);
00204 
00205   key.data = __alloca (key.size);
00206   ((char *) key.data)[0] = '.';
00207   memcpy (&((char *) key.data)[1], name, key.size - 1);
00208   key.flags = 0;
00209 
00210   __libc_lock_lock (lock);
00211   status = lookup (&key, result, buffer, buflen, errnop);
00212   __libc_lock_unlock (lock);
00213 
00214   return status;
00215 }