1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19: #include <ctype.h>
20: #include <errno.h>
21: #include <error.h>
22: #include <libintl.h>
23: #include <malloc.h>
24: #include <pwd.h>
25: #include <stdio.h>
26: #include <stdio_ext.h>
27: #include <stdlib.h>
28: #include <string.h>
29: #include <unistd.h>
30: #include <sys/param.h>
31: #include <sys/types.h>
32:
33: #include "dbg_log.h"
34: #include "nscd.h"
35:
36:
37: extern char *xstrdup (const char *s);
38:
39:
40:
41: const char *const dbnames[lastdb] =
42: {
43: [pwddb] = "passwd",
44: [grpdb] = "group",
45: [hstdb] = "hosts",
46: [servdb] = "services"
47: };
48:
49:
50: static int
51: find_db (const char *name)
52: {
53: for (int cnt = 0; cnt < lastdb; ++cnt)
54: if (strcmp (name, dbnames[cnt]) == 0)
55: return cnt;
56:
57: error (0, 0, _("database %s is not supported"), name);
58: return -1;
59: }
60:
61: int
62: nscd_parse_file (const char *fname, struct database_dyn dbs[lastdb])
63: {
64: FILE *fp;
65: char *line, *cp, *entry, *arg1, *arg2;
66: size_t len;
67: int cnt;
68: const unsigned int initial_error_message_count = error_message_count;
69:
70:
71: fp = fopen (fname, "r");
72: if (fp == NULL)
73: return -1;
74:
75:
76: (void) __fsetlocking (fp, FSETLOCKING_BYCALLER);
77:
78: line = NULL;
79: len = 0;
80:
81: do
82: {
83: ssize_t n = getline (&line, &len, fp);
84: if (n < 0)
85: break;
86: if (line[n - 1] == '\n')
87: line[n - 1] = '\0';
88:
89:
90:
91:
92: *strchrnul (line, '#') = '\0';
93:
94:
95: if (line[0] == '\0')
96: continue;
97:
98: entry = line;
99: while (isspace (*entry) && *entry != '\0')
100: ++entry;
101: cp = entry;
102: while (!isspace (*cp) && *cp != '\0')
103: ++cp;
104: arg1 = cp;
105: ++arg1;
106: *cp = '\0';
107: if (strlen (entry) == 0)
108: error (0, 0, _("Parse error: %s"), line);
109: while (isspace (*arg1) && *arg1 != '\0')
110: ++arg1;
111: cp = arg1;
112: while (!isspace (*cp) && *cp != '\0')
113: ++cp;
114: arg2 = cp;
115: ++arg2;
116: *cp = '\0';
117: if (strlen (arg2) > 0)
118: {
119: while (isspace (*arg2) && *arg2 != '\0')
120: ++arg2;
121: cp = arg2;
122: while (!isspace (*cp) && *cp != '\0')
123: ++cp;
124: *cp = '\0';
125: }
126:
127: if (strcmp (entry, "positive-time-to-live") == 0)
128: {
129: int idx = find_db (arg1);
130: if (idx >= 0)
131: dbs[idx].postimeout = atol (arg2);
132: }
133: else if (strcmp (entry, "negative-time-to-live") == 0)
134: {
135: int idx = find_db (arg1);
136: if (idx >= 0)
137: dbs[idx].negtimeout = atol (arg2);
138: }
139: else if (strcmp (entry, "suggested-size") == 0)
140: {
141: int idx = find_db (arg1);
142: if (idx >= 0)
143: dbs[idx].suggested_module = atol (arg2);
144: }
145: else if (strcmp (entry, "enable-cache") == 0)
146: {
147: int idx = find_db (arg1);
148: if (idx >= 0)
149: {
150: if (strcmp (arg2, "no") == 0)
151: dbs[idx].enabled = 0;
152: else if (strcmp (arg2, "yes") == 0)
153: dbs[idx].enabled = 1;
154: }
155: }
156: else if (strcmp (entry, "check-files") == 0)
157: {
158: int idx = find_db (arg1);
159: if (idx >= 0)
160: {
161: if (strcmp (arg2, "no") == 0)
162: dbs[idx].check_file = 0;
163: else if (strcmp (arg2, "yes") == 0)
164: dbs[idx].check_file = 1;
165: }
166: }
167: else if (strcmp (entry, "max-db-size") == 0)
168: {
169: int idx = find_db (arg1);
170: if (idx >= 0)
171: dbs[idx].max_db_size = atol (arg2);
172: }
173: else if (strcmp (entry, "logfile") == 0)
174: set_logfile (arg1);
175: else if (strcmp (entry, "debug-level") == 0)
176: {
177: int level = atoi (arg1);
178: if (level > 0)
179: debug_level = level;
180: }
181: else if (strcmp (entry, "threads") == 0)
182: {
183: if (nthreads == -1)
184: nthreads = MAX (atol (arg1), lastdb);
185: }
186: else if (strcmp (entry, "max-threads") == 0)
187: {
188: max_nthreads = MAX (atol (arg1), lastdb);
189: }
190: else if (strcmp (entry, "server-user") == 0)
191: {
192: if (!arg1)
193: error (0, 0, _("Must specify user name for server-user option"));
194: else
195: server_user = xstrdup (arg1);
196: }
197: else if (strcmp (entry, "stat-user") == 0)
198: {
199: if (arg1 == NULL)
200: error (0, 0, _("Must specify user name for stat-user option"));
201: else
202: {
203: stat_user = xstrdup (arg1);
204:
205: struct passwd *pw = getpwnam (stat_user);
206: if (pw != NULL)
207: stat_uid = pw->pw_uid;
208: }
209: }
210: else if (strcmp (entry, "persistent") == 0)
211: {
212: int idx = find_db (arg1);
213: if (idx >= 0)
214: {
215: if (strcmp (arg2, "no") == 0)
216: dbs[idx].persistent = 0;
217: else if (strcmp (arg2, "yes") == 0)
218: dbs[idx].persistent = 1;
219: }
220: }
221: else if (strcmp (entry, "shared") == 0)
222: {
223: int idx = find_db (arg1);
224: if (idx >= 0)
225: {
226: if (strcmp (arg2, "no") == 0)
227: dbs[idx].shared = 0;
228: else if (strcmp (arg2, "yes") == 0)
229: dbs[idx].shared = 1;
230: }
231: }
232: else if (strcmp (entry, "reload-count") == 0)
233: {
234: if (strcasecmp (arg1, "unlimited") == 0)
235: reload_count = UINT_MAX;
236: else
237: {
238: unsigned int count = strtoul (arg1, NULL, 0);
239: if (count > UINT8_MAX - 1)
240: reload_count = UINT_MAX;
241: else if (count >= 0)
242: reload_count = count;
243: else
244: error (0, 0, _("invalid value for 'reload-count': %u"), count);
245: }
246: }
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
259: error (0, 0, _("Must specify value for restart-interval option"));
260: }
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: }
272: else
273: error (0, 0, _("Unknown option: %s %s %s"), entry, arg1, arg2);
274: }
275: while (!feof_unlocked (fp));
276:
277: if (paranoia)
278: {
279: restart_time = time (NULL) + restart_interval;
280:
281:
282:
283: oldcwd = get_current_dir_name ();
284: if (oldcwd == NULL)
285: {
286: error (0, 0, _("\
287: cannot get current working directory: %s; disabling paranoia mode"),
288: strerror (errno));
289: paranoia = 0;
290: }
291: }
292:
293:
294: if (max_nthreads < nthreads)
295: max_nthreads = nthreads;
296:
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: {
306: error (0, 0, _("maximum file size for %s database too small"),
307: dbnames[cnt]);
308: dbs[cnt].max_db_size = datasize;
309: }
310:
311: }
312:
313:
314: free (line);
315:
316: fclose (fp);
317:
318: return error_message_count != initial_error_message_count;
319: }