Back to index

glibc  2.9
nscd_conf.c
Go to the documentation of this file.
00001 /* Copyright (c) 1998, 2000, 2003-2007, 2008 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
00004 
00005    This program is free software; you can redistribute it and/or modify
00006    it under the terms of the GNU General Public License as published
00007    by the Free Software Foundation; version 2 of the License, or
00008    (at your option) any later version.
00009 
00010    This program 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
00013    GNU General Public License for more details.
00014 
00015    You should have received a copy of the GNU General Public License
00016    along with this program; if not, write to the Free Software Foundation,
00017    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
00018 
00019 #include <ctype.h>
00020 #include <errno.h>
00021 #include <error.h>
00022 #include <libintl.h>
00023 #include <malloc.h>
00024 #include <pwd.h>
00025 #include <stdio.h>
00026 #include <stdio_ext.h>
00027 #include <stdlib.h>
00028 #include <string.h>
00029 #include <unistd.h>
00030 #include <sys/param.h>
00031 #include <sys/types.h>
00032 
00033 #include "dbg_log.h"
00034 #include "nscd.h"
00035 
00036 /* Wrapper functions with error checking for standard functions.  */
00037 extern char *xstrdup (const char *s);
00038 
00039 
00040 /* Names of the databases.  */
00041 const char *const dbnames[lastdb] =
00042 {
00043   [pwddb] = "passwd",
00044   [grpdb] = "group",
00045   [hstdb] = "hosts",
00046   [servdb] = "services"
00047 };
00048 
00049 
00050 static int
00051 find_db (const char *name)
00052 {
00053   for (int cnt = 0; cnt < lastdb; ++cnt)
00054     if (strcmp (name, dbnames[cnt]) == 0)
00055       return cnt;
00056 
00057   error (0, 0, _("database %s is not supported"), name);
00058   return -1;
00059 }
00060 
00061 int
00062 nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb])
00063 {
00064   FILE *fp;
00065   char *line, *cp, *entry, *arg1, *arg2;
00066   size_t len;
00067   int cnt;
00068   const unsigned int initial_error_message_count = error_message_count;
00069 
00070   /* Open the configuration file.  */
00071   fp = fopen (fname, "r");
00072   if (fp == NULL)
00073     return -1;
00074 
00075   /* The stream is not used by more than one thread.  */
00076   (void) __fsetlocking (fp, FSETLOCKING_BYCALLER);
00077 
00078   line = NULL;
00079   len = 0;
00080 
00081   do
00082     {
00083       ssize_t n = getline (&line, &len, fp);
00084       if (n < 0)
00085        break;
00086       if (line[n - 1] == '\n')
00087        line[n - 1] = '\0';
00088 
00089       /* Because the file format does not know any form of quoting we
00090         can search forward for the next '#' character and if found
00091         make it terminating the line.  */
00092       *strchrnul (line, '#') = '\0';
00093 
00094       /* If the line is blank it is ignored.  */
00095       if (line[0] == '\0')
00096        continue;
00097 
00098       entry = line;
00099       while (isspace (*entry) && *entry != '\0')
00100        ++entry;
00101       cp = entry;
00102       while (!isspace (*cp) && *cp != '\0')
00103        ++cp;
00104       arg1 = cp;
00105       ++arg1;
00106       *cp = '\0';
00107       if (strlen (entry) == 0)
00108        error (0, 0, _("Parse error: %s"), line);
00109       while (isspace (*arg1) && *arg1 != '\0')
00110        ++arg1;
00111       cp = arg1;
00112       while (!isspace (*cp) && *cp != '\0')
00113        ++cp;
00114       arg2 = cp;
00115       ++arg2;
00116       *cp = '\0';
00117       if (strlen (arg2) > 0)
00118        {
00119          while (isspace (*arg2) && *arg2 != '\0')
00120            ++arg2;
00121          cp = arg2;
00122          while (!isspace (*cp) && *cp != '\0')
00123            ++cp;
00124          *cp = '\0';
00125        }
00126 
00127       if (strcmp (entry, "positive-time-to-live") == 0)
00128        {
00129          int idx = find_db (arg1);
00130          if (idx >= 0)
00131            dbs[idx].postimeout = atol (arg2);
00132        }
00133       else if (strcmp (entry, "negative-time-to-live") == 0)
00134        {
00135          int idx = find_db (arg1);
00136          if (idx >= 0)
00137            dbs[idx].negtimeout = atol (arg2);
00138        }
00139       else if (strcmp (entry, "suggested-size") == 0)
00140        {
00141          int idx = find_db (arg1);
00142          if (idx >= 0)
00143            dbs[idx].suggested_module
00144              = atol (arg2) ?: DEFAULT_SUGGESTED_MODULE;
00145        }
00146       else if (strcmp (entry, "enable-cache") == 0)
00147        {
00148          int idx = find_db (arg1);
00149          if (idx >= 0)
00150            {
00151              if (strcmp (arg2, "no") == 0)
00152               dbs[idx].enabled = 0;
00153              else if (strcmp (arg2, "yes") == 0)
00154               dbs[idx].enabled = 1;
00155            }
00156        }
00157       else if (strcmp (entry, "check-files") == 0)
00158        {
00159          int idx = find_db (arg1);
00160          if (idx >= 0)
00161            {
00162              if (strcmp (arg2, "no") == 0)
00163               dbs[idx].check_file = 0;
00164              else if (strcmp (arg2, "yes") == 0)
00165               dbs[idx].check_file = 1;
00166            }
00167        }
00168       else if (strcmp (entry, "max-db-size") == 0)
00169        {
00170          int idx = find_db (arg1);
00171          if (idx >= 0)
00172            dbs[idx].max_db_size = atol (arg2) ?: DEFAULT_MAX_DB_SIZE;
00173        }
00174       else if (strcmp (entry, "logfile") == 0)
00175        set_logfile (arg1);
00176       else if (strcmp (entry, "debug-level") == 0)
00177        {
00178          int level = atoi (arg1);
00179          if (level > 0)
00180            debug_level = level;
00181        }
00182       else if (strcmp (entry, "threads") == 0)
00183        {
00184          if (nthreads == -1)
00185            nthreads = MAX (atol (arg1), lastdb);
00186        }
00187       else if (strcmp (entry, "max-threads") == 0)
00188        {
00189          max_nthreads = MAX (atol (arg1), lastdb);
00190        }
00191       else if (strcmp (entry, "server-user") == 0)
00192         {
00193           if (!arg1)
00194             error (0, 0, _("Must specify user name for server-user option"));
00195           else
00196             server_user = xstrdup (arg1);
00197         }
00198       else if (strcmp (entry, "stat-user") == 0)
00199         {
00200           if (arg1 == NULL)
00201             error (0, 0, _("Must specify user name for stat-user option"));
00202           else
00203            {
00204              stat_user = xstrdup (arg1);
00205 
00206              struct passwd *pw = getpwnam (stat_user);
00207              if (pw != NULL)
00208               stat_uid = pw->pw_uid;
00209            }
00210         }
00211       else if (strcmp (entry, "persistent") == 0)
00212        {
00213          int idx = find_db (arg1);
00214          if (idx >= 0)
00215            {
00216              if (strcmp (arg2, "no") == 0)
00217               dbs[idx].persistent = 0;
00218              else if (strcmp (arg2, "yes") == 0)
00219               dbs[idx].persistent = 1;
00220            }
00221        }
00222       else if (strcmp (entry, "shared") == 0)
00223        {
00224          int idx = find_db (arg1);
00225          if (idx >= 0)
00226            {
00227              if (strcmp (arg2, "no") == 0)
00228               dbs[idx].shared = 0;
00229              else if (strcmp (arg2, "yes") == 0)
00230               dbs[idx].shared = 1;
00231            }
00232        }
00233       else if (strcmp (entry, "reload-count") == 0)
00234        {
00235          if (strcasecmp (arg1, "unlimited") == 0)
00236            reload_count = UINT_MAX;
00237          else
00238            {
00239              unsigned int count = strtoul (arg1, NULL, 0);
00240              if (count > UINT8_MAX - 1)
00241               reload_count = UINT_MAX;
00242              else if (count >= 0)
00243            reload_count = count;
00244              else
00245               error (0, 0, _("invalid value for 'reload-count': %u"), count);
00246            }
00247        }
00248       else if (strcmp (entry, "paranoia") == 0)
00249        {
00250          if (strcmp (arg1, "no") == 0)
00251            paranoia = 0;
00252          else if (strcmp (arg1, "yes") == 0)
00253            paranoia = 1;
00254        }
00255       else if (strcmp (entry, "restart-interval") == 0)
00256        {
00257          if (arg1 != NULL)
00258            restart_interval = atol (arg1);
00259          else
00260             error (0, 0, _("Must specify value for restart-interval option"));
00261        }
00262       else if (strcmp (entry, "auto-propagate") == 0)
00263        {
00264          int idx = find_db (arg1);
00265          if (idx >= 0)
00266            {
00267              if (strcmp (arg2, "no") == 0)
00268               dbs[idx].propagate = 0;
00269              else if (strcmp (arg2, "yes") == 0)
00270               dbs[idx].propagate = 1;
00271            }
00272        }
00273       else
00274        error (0, 0, _("Unknown option: %s %s %s"), entry, arg1, arg2);
00275     }
00276   while (!feof_unlocked (fp));
00277 
00278   if (paranoia)
00279     {
00280       restart_time = time (NULL) + restart_interval;
00281 
00282       /* Save the old current workding directory if we are in paranoia
00283         mode.  We have to change back to it.  */
00284       oldcwd = get_current_dir_name ();
00285       if (oldcwd == NULL)
00286        {
00287          error (0, 0, _("\
00288 cannot get current working directory: %s; disabling paranoia mode"),
00289                  strerror (errno));
00290          paranoia = 0;
00291        }
00292     }
00293 
00294   /* Enforce sanity.  */
00295   if (max_nthreads < nthreads)
00296     max_nthreads = nthreads;
00297 
00298   for (cnt = 0; cnt < lastdb; ++cnt)
00299     {
00300       size_t datasize = (sizeof (struct database_pers_head)
00301                       + roundup (dbs[cnt].suggested_module
00302                                 * sizeof (ref_t), ALIGN)
00303                       + (dbs[cnt].suggested_module
00304                          * DEFAULT_DATASIZE_PER_BUCKET));
00305       if (datasize > dbs[cnt].max_db_size)
00306        {
00307          error (0, 0, _("maximum file size for %s database too small"),
00308                  dbnames[cnt]);
00309          dbs[cnt].max_db_size = datasize;
00310        }
00311 
00312     }
00313 
00314   /* Free the buffer.  */
00315   free (line);
00316   /* Close configuration file.  */
00317   fclose (fp);
00318 
00319   return error_message_count != initial_error_message_count;
00320 }