nscd_conf.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /* Copyright (c) 1998-2026 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published
  5. by the Free Software Foundation; version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, see <https://www.gnu.org/licenses/>. */
  13. #include <ctype.h>
  14. #include <errno.h>
  15. #include <error.h>
  16. #include <libintl.h>
  17. #include <malloc.h>
  18. #include <pwd.h>
  19. #include <stdio.h>
  20. #include <stdio_ext.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <unistd.h>
  24. #include <sys/param.h>
  25. #include <sys/types.h>
  26. #include "dbg_log.h"
  27. #include "nscd.h"
  28. /* Names of the databases. */
  29. const char *const dbnames[lastdb] =
  30. {
  31. [pwddb] = "passwd",
  32. [grpdb] = "group",
  33. [hstdb] = "hosts",
  34. [servdb] = "services",
  35. [netgrdb] = "netgroup"
  36. };
  37. static int
  38. find_db (const char *name)
  39. {
  40. for (int cnt = 0; cnt < lastdb; ++cnt)
  41. if (strcmp (name, dbnames[cnt]) == 0)
  42. return cnt;
  43. error (0, 0, _("database %s is not supported"), name);
  44. return -1;
  45. }
  46. int
  47. nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb])
  48. {
  49. FILE *fp;
  50. char *line, *cp, *entry, *arg1, *arg2;
  51. size_t len;
  52. int cnt;
  53. const unsigned int initial_error_message_count = error_message_count;
  54. /* Open the configuration file. */
  55. fp = fopen (fname, "r");
  56. if (fp == NULL)
  57. return -1;
  58. /* The stream is not used by more than one thread. */
  59. (void) __fsetlocking (fp, FSETLOCKING_BYCALLER);
  60. line = NULL;
  61. len = 0;
  62. do
  63. {
  64. ssize_t n = getline (&line, &len, fp);
  65. if (n < 0)
  66. break;
  67. if (line[n - 1] == '\n')
  68. line[n - 1] = '\0';
  69. /* Because the file format does not know any form of quoting we
  70. can search forward for the next '#' character and if found
  71. make it terminating the line. */
  72. *strchrnul (line, '#') = '\0';
  73. /* If the line is blank it is ignored. */
  74. if (line[0] == '\0')
  75. continue;
  76. entry = line;
  77. while (isspace (*entry) && *entry != '\0')
  78. ++entry;
  79. cp = entry;
  80. while (!isspace (*cp) && *cp != '\0')
  81. ++cp;
  82. arg1 = cp;
  83. ++arg1;
  84. *cp = '\0';
  85. if (strlen (entry) == 0)
  86. error (0, 0, _("Parse error: %s"), line);
  87. while (isspace (*arg1) && *arg1 != '\0')
  88. ++arg1;
  89. cp = arg1;
  90. while (!isspace (*cp) && *cp != '\0')
  91. ++cp;
  92. arg2 = cp;
  93. ++arg2;
  94. *cp = '\0';
  95. if (strlen (arg2) > 0)
  96. {
  97. while (isspace (*arg2) && *arg2 != '\0')
  98. ++arg2;
  99. cp = arg2;
  100. while (!isspace (*cp) && *cp != '\0')
  101. ++cp;
  102. *cp = '\0';
  103. }
  104. if (strcmp (entry, "positive-time-to-live") == 0)
  105. {
  106. int idx = find_db (arg1);
  107. if (idx >= 0)
  108. dbs[idx].postimeout = atol (arg2);
  109. }
  110. else if (strcmp (entry, "negative-time-to-live") == 0)
  111. {
  112. int idx = find_db (arg1);
  113. if (idx >= 0)
  114. dbs[idx].negtimeout = atol (arg2);
  115. }
  116. else if (strcmp (entry, "suggested-size") == 0)
  117. {
  118. int idx = find_db (arg1);
  119. if (idx >= 0)
  120. dbs[idx].suggested_module
  121. = atol (arg2) ?: DEFAULT_SUGGESTED_MODULE;
  122. }
  123. else if (strcmp (entry, "enable-cache") == 0)
  124. {
  125. int idx = find_db (arg1);
  126. if (idx >= 0)
  127. {
  128. if (strcmp (arg2, "no") == 0)
  129. dbs[idx].enabled = 0;
  130. else if (strcmp (arg2, "yes") == 0)
  131. dbs[idx].enabled = 1;
  132. }
  133. }
  134. else if (strcmp (entry, "check-files") == 0)
  135. {
  136. int idx = find_db (arg1);
  137. if (idx >= 0)
  138. {
  139. if (strcmp (arg2, "no") == 0)
  140. dbs[idx].check_file = 0;
  141. else if (strcmp (arg2, "yes") == 0)
  142. dbs[idx].check_file = 1;
  143. }
  144. }
  145. else if (strcmp (entry, "max-db-size") == 0)
  146. {
  147. int idx = find_db (arg1);
  148. if (idx >= 0)
  149. dbs[idx].max_db_size = atol (arg2) ?: DEFAULT_MAX_DB_SIZE;
  150. }
  151. else if (strcmp (entry, "logfile") == 0)
  152. set_logfile (arg1);
  153. else if (strcmp (entry, "debug-level") == 0)
  154. {
  155. int level = atoi (arg1);
  156. if (level > 0)
  157. debug_level = level;
  158. }
  159. else if (strcmp (entry, "threads") == 0)
  160. {
  161. if (nthreads == -1)
  162. nthreads = MAX (atol (arg1), lastdb);
  163. }
  164. else if (strcmp (entry, "max-threads") == 0)
  165. {
  166. max_nthreads = MAX (atol (arg1), lastdb);
  167. }
  168. else if (strcmp (entry, "server-user") == 0)
  169. {
  170. if (!arg1)
  171. error (0, 0, _("Must specify user name for server-user option"));
  172. else
  173. {
  174. free ((char *) server_user);
  175. server_user = xstrdup (arg1);
  176. }
  177. }
  178. else if (strcmp (entry, "stat-user") == 0)
  179. {
  180. if (arg1 == NULL)
  181. error (0, 0, _("Must specify user name for stat-user option"));
  182. else
  183. {
  184. free ((char *) stat_user);
  185. stat_user = xstrdup (arg1);
  186. struct passwd *pw = getpwnam (stat_user);
  187. if (pw != NULL)
  188. stat_uid = pw->pw_uid;
  189. }
  190. }
  191. else if (strcmp (entry, "persistent") == 0)
  192. {
  193. int idx = find_db (arg1);
  194. if (idx >= 0)
  195. {
  196. if (strcmp (arg2, "no") == 0)
  197. dbs[idx].persistent = 0;
  198. else if (strcmp (arg2, "yes") == 0)
  199. dbs[idx].persistent = 1;
  200. }
  201. }
  202. else if (strcmp (entry, "shared") == 0)
  203. {
  204. int idx = find_db (arg1);
  205. if (idx >= 0)
  206. {
  207. if (strcmp (arg2, "no") == 0)
  208. dbs[idx].shared = 0;
  209. else if (strcmp (arg2, "yes") == 0)
  210. dbs[idx].shared = 1;
  211. }
  212. }
  213. else if (strcmp (entry, "reload-count") == 0)
  214. {
  215. if (strcasecmp (arg1, "unlimited") == 0)
  216. reload_count = UINT_MAX;
  217. else
  218. {
  219. unsigned long int count = strtoul (arg1, NULL, 0);
  220. if (count > UINT8_MAX - 1)
  221. reload_count = UINT_MAX;
  222. else
  223. reload_count = count;
  224. }
  225. }
  226. else if (strcmp (entry, "paranoia") == 0)
  227. {
  228. if (strcmp (arg1, "no") == 0)
  229. paranoia = 0;
  230. else if (strcmp (arg1, "yes") == 0)
  231. paranoia = 1;
  232. }
  233. else if (strcmp (entry, "restart-interval") == 0)
  234. {
  235. if (arg1 != NULL)
  236. restart_interval = atol (arg1);
  237. else
  238. error (0, 0, _("Must specify value for restart-interval option"));
  239. }
  240. else if (strcmp (entry, "auto-propagate") == 0)
  241. {
  242. int idx = find_db (arg1);
  243. if (idx >= 0)
  244. {
  245. if (strcmp (arg2, "no") == 0)
  246. dbs[idx].propagate = 0;
  247. else if (strcmp (arg2, "yes") == 0)
  248. dbs[idx].propagate = 1;
  249. }
  250. }
  251. else
  252. error (0, 0, _("Unknown option: %s %s %s"), entry, arg1, arg2);
  253. }
  254. while (!feof_unlocked (fp));
  255. if (paranoia)
  256. {
  257. restart_time = time (NULL) + restart_interval;
  258. /* Save the old current workding directory if we are in paranoia
  259. mode. We have to change back to it. */
  260. oldcwd = get_current_dir_name ();
  261. if (oldcwd == NULL)
  262. {
  263. error (0, 0, _("\
  264. cannot get current working directory: %s; disabling paranoia mode"),
  265. strerror (errno));
  266. paranoia = 0;
  267. }
  268. }
  269. /* Enforce sanity. */
  270. if (max_nthreads < nthreads)
  271. max_nthreads = nthreads;
  272. for (cnt = 0; cnt < lastdb; ++cnt)
  273. {
  274. size_t datasize = (sizeof (struct database_pers_head)
  275. + roundup (dbs[cnt].suggested_module
  276. * sizeof (ref_t), ALIGN)
  277. + (dbs[cnt].suggested_module
  278. * DEFAULT_DATASIZE_PER_BUCKET));
  279. if (datasize > dbs[cnt].max_db_size)
  280. {
  281. error (0, 0, _("maximum file size for %s database too small"),
  282. dbnames[cnt]);
  283. dbs[cnt].max_db_size = datasize;
  284. }
  285. }
  286. /* Free the buffer. */
  287. free (line);
  288. /* Close configuration file. */
  289. fclose (fp);
  290. return error_message_count != initial_error_message_count;
  291. }