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