]>
Commit | Line | Data |
---|---|---|
f7a9f785 | 1 | /* Copyright (c) 1998-2016 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 |
59ba27a6 | 16 | along with this program; if not, see <http://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 | |
193 | server_user = xstrdup (arg1); | |
194 | } | |
a12ce44f | 195 | else if (strcmp (entry, "stat-user") == 0) |
b902330c MP |
196 | { |
197 | if (arg1 == NULL) | |
198 | error (0, 0, _("Must specify user name for stat-user option")); | |
199 | else | |
a12ce44f UD |
200 | { |
201 | stat_user = xstrdup (arg1); | |
202 | ||
203 | struct passwd *pw = getpwnam (stat_user); | |
204 | if (pw != NULL) | |
205 | stat_uid = pw->pw_uid; | |
206 | } | |
b902330c | 207 | } |
a95a08b4 UD |
208 | else if (strcmp (entry, "persistent") == 0) |
209 | { | |
4fb5ab74 UD |
210 | int idx = find_db (arg1); |
211 | if (idx >= 0) | |
212 | { | |
213 | if (strcmp (arg2, "no") == 0) | |
214 | dbs[idx].persistent = 0; | |
215 | else if (strcmp (arg2, "yes") == 0) | |
216 | dbs[idx].persistent = 1; | |
217 | } | |
a95a08b4 | 218 | } |
c207f23b UD |
219 | else if (strcmp (entry, "shared") == 0) |
220 | { | |
4fb5ab74 UD |
221 | int idx = find_db (arg1); |
222 | if (idx >= 0) | |
223 | { | |
224 | if (strcmp (arg2, "no") == 0) | |
225 | dbs[idx].shared = 0; | |
226 | else if (strcmp (arg2, "yes") == 0) | |
227 | dbs[idx].shared = 1; | |
228 | } | |
c207f23b | 229 | } |
a95a08b4 UD |
230 | else if (strcmp (entry, "reload-count") == 0) |
231 | { | |
232 | if (strcasecmp (arg1, "unlimited") == 0) | |
233 | reload_count = UINT_MAX; | |
234 | else | |
235 | { | |
b902330c | 236 | unsigned long int count = strtoul (arg1, NULL, 0); |
a95a08b4 UD |
237 | if (count > UINT8_MAX - 1) |
238 | reload_count = UINT_MAX; | |
a95a08b4 | 239 | else |
b902330c | 240 | reload_count = count; |
a95a08b4 UD |
241 | } |
242 | } | |
4401d759 UD |
243 | else if (strcmp (entry, "paranoia") == 0) |
244 | { | |
245 | if (strcmp (arg1, "no") == 0) | |
246 | paranoia = 0; | |
247 | else if (strcmp (arg1, "yes") == 0) | |
248 | paranoia = 1; | |
249 | } | |
250 | else if (strcmp (entry, "restart-interval") == 0) | |
251 | { | |
252 | if (arg1 != NULL) | |
253 | restart_interval = atol (arg1); | |
254 | else | |
b902330c | 255 | error (0, 0, _("Must specify value for restart-interval option")); |
4401d759 | 256 | } |
797ed6f7 UD |
257 | else if (strcmp (entry, "auto-propagate") == 0) |
258 | { | |
259 | int idx = find_db (arg1); | |
260 | if (idx >= 0) | |
261 | { | |
262 | if (strcmp (arg2, "no") == 0) | |
263 | dbs[idx].propagate = 0; | |
264 | else if (strcmp (arg2, "yes") == 0) | |
265 | dbs[idx].propagate = 1; | |
266 | } | |
267 | } | |
d67281a7 | 268 | else |
4fb5ab74 | 269 | error (0, 0, _("Unknown option: %s %s %s"), entry, arg1, arg2); |
d67281a7 | 270 | } |
f4047366 | 271 | while (!feof_unlocked (fp)); |
d67281a7 | 272 | |
4401d759 UD |
273 | if (paranoia) |
274 | { | |
275 | restart_time = time (NULL) + restart_interval; | |
276 | ||
277 | /* Save the old current workding directory if we are in paranoia | |
278 | mode. We have to change back to it. */ | |
279 | oldcwd = get_current_dir_name (); | |
280 | if (oldcwd == NULL) | |
281 | { | |
4fb5ab74 | 282 | error (0, 0, _("\ |
4401d759 UD |
283 | cannot get current working directory: %s; disabling paranoia mode"), |
284 | strerror (errno)); | |
285 | paranoia = 0; | |
286 | } | |
287 | } | |
288 | ||
27e82856 UD |
289 | /* Enforce sanity. */ |
290 | if (max_nthreads < nthreads) | |
291 | max_nthreads = nthreads; | |
292 | ||
2c210d1e UD |
293 | for (cnt = 0; cnt < lastdb; ++cnt) |
294 | { | |
295 | size_t datasize = (sizeof (struct database_pers_head) | |
296 | + roundup (dbs[cnt].suggested_module | |
297 | * sizeof (ref_t), ALIGN) | |
298 | + (dbs[cnt].suggested_module | |
299 | * DEFAULT_DATASIZE_PER_BUCKET)); | |
300 | if (datasize > dbs[cnt].max_db_size) | |
301 | { | |
4fb5ab74 | 302 | error (0, 0, _("maximum file size for %s database too small"), |
2c210d1e UD |
303 | dbnames[cnt]); |
304 | dbs[cnt].max_db_size = datasize; | |
305 | } | |
306 | ||
307 | } | |
308 | ||
d67281a7 UD |
309 | /* Free the buffer. */ |
310 | free (line); | |
311 | /* Close configuration file. */ | |
312 | fclose (fp); | |
313 | ||
4fb5ab74 | 314 | return error_message_count != initial_error_message_count; |
d67281a7 | 315 | } |