xref: /netbsd-src/external/bsd/libbind/dist/irs/gen.c (revision 5bbd2a12505d72a8177929a37b5cee489d0a1cfd)
1*5bbd2a12Schristos /*	$NetBSD: gen.c,v 1.1.1.2 2012/09/09 16:07:55 christos Exp $	*/
2b5677b36Schristos 
3b5677b36Schristos /*
4b5677b36Schristos  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
5b5677b36Schristos  * Copyright (c) 1996-1999 by Internet Software Consortium.
6b5677b36Schristos  *
7b5677b36Schristos  * Permission to use, copy, modify, and distribute this software for any
8b5677b36Schristos  * purpose with or without fee is hereby granted, provided that the above
9b5677b36Schristos  * copyright notice and this permission notice appear in all copies.
10b5677b36Schristos  *
11b5677b36Schristos  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
12b5677b36Schristos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13b5677b36Schristos  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
14b5677b36Schristos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15b5677b36Schristos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16b5677b36Schristos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17b5677b36Schristos  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18b5677b36Schristos  */
19b5677b36Schristos 
20b5677b36Schristos #if !defined(LINT) && !defined(CODECENTER)
21b5677b36Schristos static const char rcsid[] = "Id: gen.c,v 1.7 2005/04/27 04:56:23 sra Exp ";
22b5677b36Schristos #endif
23b5677b36Schristos 
24b5677b36Schristos /*! \file
25b5677b36Schristos  * \brief
26b5677b36Schristos  * this is the top level dispatcher
27b5677b36Schristos  *
28b5677b36Schristos  * The dispatcher is implemented as an accessor class; it is an
29b5677b36Schristos  * accessor class that calls other accessor classes, as controlled by a
30b5677b36Schristos  * configuration file.
31b5677b36Schristos  *
32b5677b36Schristos  * A big difference between this accessor class and others is that the
33b5677b36Schristos  * map class initializers are NULL, and the map classes are already
34b5677b36Schristos  * filled in with method functions that will do the right thing.
35b5677b36Schristos  */
36b5677b36Schristos 
37b5677b36Schristos /* Imports */
38b5677b36Schristos 
39b5677b36Schristos #include "port_before.h"
40b5677b36Schristos 
41b5677b36Schristos #include <isc/assertions.h>
42b5677b36Schristos #include <ctype.h>
43b5677b36Schristos #include <errno.h>
44b5677b36Schristos #include <stdio.h>
45b5677b36Schristos #include <stdlib.h>
46b5677b36Schristos #include <string.h>
47b5677b36Schristos 
48b5677b36Schristos #include <sys/types.h>
49b5677b36Schristos #include <netinet/in.h>
50b5677b36Schristos #include <arpa/nameser.h>
51b5677b36Schristos #include <resolv.h>
52b5677b36Schristos 
53b5677b36Schristos #include <isc/memcluster.h>
54b5677b36Schristos #include <irs.h>
55b5677b36Schristos 
56b5677b36Schristos #include "port_after.h"
57b5677b36Schristos 
58b5677b36Schristos #include "irs_p.h"
59b5677b36Schristos #include "gen_p.h"
60b5677b36Schristos 
61b5677b36Schristos /* Definitions */
62b5677b36Schristos 
63b5677b36Schristos struct nameval {
64b5677b36Schristos 	const char *	name;
65b5677b36Schristos 	int		val;
66b5677b36Schristos };
67b5677b36Schristos 
68b5677b36Schristos static const struct nameval acc_names[irs_nacc+1] = {
69b5677b36Schristos 	{ "local", irs_lcl },
70b5677b36Schristos 	{ "dns", irs_dns },
71b5677b36Schristos 	{ "nis", irs_nis },
72b5677b36Schristos 	{ "irp", irs_irp },
73b5677b36Schristos 	{ NULL, irs_nacc }
74b5677b36Schristos };
75b5677b36Schristos 
76b5677b36Schristos typedef struct irs_acc *(*accinit) __P((const char *options));
77b5677b36Schristos 
78b5677b36Schristos static const accinit accs[irs_nacc+1] = {
79b5677b36Schristos 	irs_lcl_acc,
80b5677b36Schristos 	irs_dns_acc,
81b5677b36Schristos #ifdef WANT_IRS_NIS
82b5677b36Schristos 	irs_nis_acc,
83b5677b36Schristos #else
84b5677b36Schristos 	NULL,
85b5677b36Schristos #endif
86b5677b36Schristos 	irs_irp_acc,
87b5677b36Schristos 	NULL
88b5677b36Schristos };
89b5677b36Schristos 
90b5677b36Schristos static const struct nameval map_names[irs_nmap+1] = {
91b5677b36Schristos 	{ "group", irs_gr },
92b5677b36Schristos 	{ "passwd", irs_pw },
93b5677b36Schristos 	{ "services", irs_sv },
94b5677b36Schristos 	{ "protocols", irs_pr },
95b5677b36Schristos 	{ "hosts", irs_ho },
96b5677b36Schristos 	{ "networks", irs_nw },
97b5677b36Schristos 	{ "netgroup", irs_ng },
98b5677b36Schristos 	{ NULL, irs_nmap }
99b5677b36Schristos };
100b5677b36Schristos 
101b5677b36Schristos static const struct nameval option_names[] = {
102b5677b36Schristos 	{ "merge", IRS_MERGE },
103b5677b36Schristos 	{ "continue", IRS_CONTINUE },
104b5677b36Schristos 	{ NULL, 0 }
105b5677b36Schristos };
106b5677b36Schristos 
107b5677b36Schristos /* Forward */
108b5677b36Schristos 
109b5677b36Schristos static void		gen_close(struct irs_acc *);
110b5677b36Schristos static struct __res_state * gen_res_get(struct irs_acc *);
111b5677b36Schristos static void		gen_res_set(struct irs_acc *, struct __res_state *,
112b5677b36Schristos 				    void (*)(void *));
113b5677b36Schristos static int		find_name(const char *, const struct nameval nv[]);
114b5677b36Schristos static void 		init_map_rules(struct gen_p *, const char *conf_file);
115b5677b36Schristos static struct irs_rule *release_rule(struct irs_rule *);
116b5677b36Schristos static int		add_rule(struct gen_p *,
117b5677b36Schristos 				 enum irs_map_id, enum irs_acc_id,
118b5677b36Schristos 				 const char *);
119b5677b36Schristos 
120b5677b36Schristos /* Public */
121b5677b36Schristos 
122b5677b36Schristos struct irs_acc *
irs_gen_acc(const char * options,const char * conf_file)123b5677b36Schristos irs_gen_acc(const char *options, const char *conf_file) {
124b5677b36Schristos 	struct irs_acc *acc;
125b5677b36Schristos 	struct gen_p *irs;
126b5677b36Schristos 
127b5677b36Schristos 	if (!(acc = memget(sizeof *acc))) {
128b5677b36Schristos 		errno = ENOMEM;
129b5677b36Schristos 		return (NULL);
130b5677b36Schristos 	}
131b5677b36Schristos 	memset(acc, 0x5e, sizeof *acc);
132b5677b36Schristos 	if (!(irs = memget(sizeof *irs))) {
133b5677b36Schristos 		errno = ENOMEM;
134b5677b36Schristos 		memput(acc, sizeof *acc);
135b5677b36Schristos 		return (NULL);
136b5677b36Schristos 	}
137b5677b36Schristos 	memset(irs, 0x5e, sizeof *irs);
138b5677b36Schristos 	irs->options = strdup(options);
139b5677b36Schristos 	irs->res = NULL;
140b5677b36Schristos 	irs->free_res = NULL;
141b5677b36Schristos 	memset(irs->accessors, 0, sizeof irs->accessors);
142b5677b36Schristos 	memset(irs->map_rules, 0, sizeof irs->map_rules);
143b5677b36Schristos 	init_map_rules(irs, conf_file);
144b5677b36Schristos 	acc->private = irs;
145b5677b36Schristos #ifdef WANT_IRS_GR
146b5677b36Schristos 	acc->gr_map = irs_gen_gr;
147b5677b36Schristos #else
148b5677b36Schristos 	acc->gr_map = NULL;
149b5677b36Schristos #endif
150b5677b36Schristos #ifdef WANT_IRS_PW
151b5677b36Schristos 	acc->pw_map = irs_gen_pw;
152b5677b36Schristos #else
153b5677b36Schristos 	acc->pw_map = NULL;
154b5677b36Schristos #endif
155b5677b36Schristos 	acc->sv_map = irs_gen_sv;
156b5677b36Schristos 	acc->pr_map = irs_gen_pr;
157b5677b36Schristos 	acc->ho_map = irs_gen_ho;
158b5677b36Schristos 	acc->nw_map = irs_gen_nw;
159b5677b36Schristos 	acc->ng_map = irs_gen_ng;
160b5677b36Schristos 	acc->res_get = gen_res_get;
161b5677b36Schristos 	acc->res_set = gen_res_set;
162b5677b36Schristos 	acc->close = gen_close;
163b5677b36Schristos 	return (acc);
164b5677b36Schristos }
165b5677b36Schristos 
166b5677b36Schristos /* Methods */
167b5677b36Schristos 
168b5677b36Schristos static struct __res_state *
gen_res_get(struct irs_acc * this)169b5677b36Schristos gen_res_get(struct irs_acc *this) {
170b5677b36Schristos 	struct gen_p *irs = (struct gen_p *)this->private;
171b5677b36Schristos 
172b5677b36Schristos 	if (irs->res == NULL) {
173b5677b36Schristos 		struct __res_state *res;
174b5677b36Schristos 		res = (struct __res_state *)malloc(sizeof *res);
175b5677b36Schristos 		if (res == NULL)
176b5677b36Schristos 			return (NULL);
177b5677b36Schristos 		memset(res, 0, sizeof *res);
178b5677b36Schristos 		gen_res_set(this, res, free);
179b5677b36Schristos 	}
180b5677b36Schristos 
181b5677b36Schristos 	if (((irs->res->options & RES_INIT) == 0U) && res_ninit(irs->res) < 0)
182b5677b36Schristos 		return (NULL);
183b5677b36Schristos 
184b5677b36Schristos 	return (irs->res);
185b5677b36Schristos }
186b5677b36Schristos 
187b5677b36Schristos static void
gen_res_set(struct irs_acc * this,struct __res_state * res,void (* free_res)(void *))188b5677b36Schristos gen_res_set(struct irs_acc *this, struct __res_state *res,
189b5677b36Schristos 	    void (*free_res)(void *)) {
190b5677b36Schristos 	struct gen_p *irs = (struct gen_p *)this->private;
191b5677b36Schristos #if 0
192b5677b36Schristos 	struct irs_rule *rule;
193b5677b36Schristos 	struct irs_ho *ho;
194b5677b36Schristos 	struct irs_nw *nw;
195b5677b36Schristos #endif
196b5677b36Schristos 
197b5677b36Schristos 	if (irs->res && irs->free_res) {
198b5677b36Schristos 		res_nclose(irs->res);
199b5677b36Schristos 		(*irs->free_res)(irs->res);
200b5677b36Schristos 	}
201b5677b36Schristos 
202b5677b36Schristos 	irs->res = res;
203b5677b36Schristos 	irs->free_res = free_res;
204b5677b36Schristos 
205b5677b36Schristos #if 0
206b5677b36Schristos 	for (rule = irs->map_rules[irs_ho]; rule; rule = rule->next) {
207b5677b36Schristos                 ho = rule->inst->ho;
208b5677b36Schristos 
209b5677b36Schristos                 (*ho->res_set)(ho, res, NULL);
210b5677b36Schristos 	}
211b5677b36Schristos 	for (rule = irs->map_rules[irs_nw]; rule; rule = rule->next) {
212b5677b36Schristos                 nw = rule->inst->nw;
213b5677b36Schristos 
214b5677b36Schristos                 (*nw->res_set)(nw, res, NULL);
215b5677b36Schristos 	}
216b5677b36Schristos #endif
217b5677b36Schristos }
218b5677b36Schristos 
219b5677b36Schristos static void
gen_close(struct irs_acc * this)220b5677b36Schristos gen_close(struct irs_acc *this) {
221b5677b36Schristos 	struct gen_p *irs = (struct gen_p *)this->private;
222b5677b36Schristos 	int n;
223b5677b36Schristos 
224b5677b36Schristos 	/* Search rules. */
225b5677b36Schristos 	for (n = 0; n < irs_nmap; n++)
226b5677b36Schristos 		while (irs->map_rules[n] != NULL)
227b5677b36Schristos 			irs->map_rules[n] = release_rule(irs->map_rules[n]);
228b5677b36Schristos 
229b5677b36Schristos 	/* Access methods. */
230b5677b36Schristos 	for (n = 0; n < irs_nacc; n++) {
231b5677b36Schristos 		/* Map objects. */
232b5677b36Schristos 		if (irs->accessors[n].gr != NULL)
233b5677b36Schristos 			(*irs->accessors[n].gr->close)(irs->accessors[n].gr);
234b5677b36Schristos 		if (irs->accessors[n].pw != NULL)
235b5677b36Schristos 			(*irs->accessors[n].pw->close)(irs->accessors[n].pw);
236b5677b36Schristos 		if (irs->accessors[n].sv != NULL)
237b5677b36Schristos 			(*irs->accessors[n].sv->close)(irs->accessors[n].sv);
238b5677b36Schristos 		if (irs->accessors[n].pr != NULL)
239b5677b36Schristos 			(*irs->accessors[n].pr->close)(irs->accessors[n].pr);
240b5677b36Schristos 		if (irs->accessors[n].ho != NULL)
241b5677b36Schristos 			(*irs->accessors[n].ho->close)(irs->accessors[n].ho);
242b5677b36Schristos 		if (irs->accessors[n].nw != NULL)
243b5677b36Schristos 			(*irs->accessors[n].nw->close)(irs->accessors[n].nw);
244b5677b36Schristos 		if (irs->accessors[n].ng != NULL)
245b5677b36Schristos 			(*irs->accessors[n].ng->close)(irs->accessors[n].ng);
246b5677b36Schristos 		/* Enclosing accessor. */
247b5677b36Schristos 		if (irs->accessors[n].acc != NULL)
248b5677b36Schristos 			(*irs->accessors[n].acc->close)(irs->accessors[n].acc);
249b5677b36Schristos 	}
250b5677b36Schristos 
251b5677b36Schristos 	/* The options string was strdup'd. */
252b5677b36Schristos 	free((void*)irs->options);
253b5677b36Schristos 
254b5677b36Schristos 	if (irs->res && irs->free_res)
255b5677b36Schristos 		(*irs->free_res)(irs->res);
256b5677b36Schristos 
257b5677b36Schristos 	/* The private data container. */
258b5677b36Schristos 	memput(irs, sizeof *irs);
259b5677b36Schristos 
260b5677b36Schristos 	/* The object. */
261b5677b36Schristos 	memput(this, sizeof *this);
262b5677b36Schristos }
263b5677b36Schristos 
264b5677b36Schristos /* Private */
265b5677b36Schristos 
266b5677b36Schristos static int
find_name(const char * name,const struct nameval names[])267b5677b36Schristos find_name(const char *name, const struct nameval names[]) {
268b5677b36Schristos 	int n;
269b5677b36Schristos 
270b5677b36Schristos 	for (n = 0; names[n].name != NULL; n++)
271b5677b36Schristos 		if (strcmp(name, names[n].name) == 0)
272b5677b36Schristos 			return (names[n].val);
273b5677b36Schristos 	return (-1);
274b5677b36Schristos }
275b5677b36Schristos 
276b5677b36Schristos static struct irs_rule *
release_rule(struct irs_rule * rule)277b5677b36Schristos release_rule(struct irs_rule *rule) {
278b5677b36Schristos 	struct irs_rule *next = rule->next;
279b5677b36Schristos 
280b5677b36Schristos 	memput(rule, sizeof *rule);
281b5677b36Schristos 	return (next);
282b5677b36Schristos }
283b5677b36Schristos 
284b5677b36Schristos static int
add_rule(struct gen_p * irs,enum irs_map_id map,enum irs_acc_id acc,const char * options)285b5677b36Schristos add_rule(struct gen_p *irs,
286b5677b36Schristos 	 enum irs_map_id map, enum irs_acc_id acc,
287b5677b36Schristos 	 const char *options)
288b5677b36Schristos {
289b5677b36Schristos 	struct irs_rule **rules, *last, *tmp, *new;
290b5677b36Schristos 	struct irs_inst *inst;
291b5677b36Schristos 	const char *cp;
292b5677b36Schristos 	int n;
293b5677b36Schristos 
294b5677b36Schristos #ifndef WANT_IRS_GR
295b5677b36Schristos 	if (map == irs_gr)
296b5677b36Schristos 		return (-1);
297b5677b36Schristos #endif
298b5677b36Schristos #ifndef WANT_IRS_PW
299b5677b36Schristos 	if (map == irs_pw)
300b5677b36Schristos 		return (-1);
301b5677b36Schristos #endif
302b5677b36Schristos #ifndef WANT_IRS_NIS
303b5677b36Schristos 	if (acc == irs_nis)
304b5677b36Schristos 		return (-1);
305b5677b36Schristos #endif
306b5677b36Schristos 	new = memget(sizeof *new);
307b5677b36Schristos 	if (new == NULL)
308b5677b36Schristos 		return (-1);
309b5677b36Schristos 	memset(new, 0x5e, sizeof *new);
310b5677b36Schristos 	new->next = NULL;
311b5677b36Schristos 
312b5677b36Schristos 	new->inst = &irs->accessors[acc];
313b5677b36Schristos 
314b5677b36Schristos 	new->flags = 0;
315b5677b36Schristos 	cp = options;
316b5677b36Schristos 	while (cp && *cp) {
317b5677b36Schristos 		char option[50], *next;
318b5677b36Schristos 
319b5677b36Schristos 		next = strchr(cp, ',');
320b5677b36Schristos 		if (next)
321b5677b36Schristos 			n = next++ - cp;
322b5677b36Schristos 		else
323b5677b36Schristos 			n = strlen(cp);
324b5677b36Schristos 		if ((size_t)n > sizeof option - 1)
325b5677b36Schristos 			n = sizeof option - 1;
326b5677b36Schristos 		strncpy(option, cp, n);
327b5677b36Schristos 		option[n] = '\0';
328b5677b36Schristos 
329b5677b36Schristos 		n = find_name(option, option_names);
330b5677b36Schristos 		if (n >= 0)
331b5677b36Schristos 			new->flags |= n;
332b5677b36Schristos 
333b5677b36Schristos 		cp = next;
334b5677b36Schristos 	}
335b5677b36Schristos 
336b5677b36Schristos 	rules = &irs->map_rules[map];
337b5677b36Schristos 	for (last = NULL, tmp = *rules;
338b5677b36Schristos 	     tmp != NULL;
339b5677b36Schristos 	     last = tmp, tmp = tmp->next)
340b5677b36Schristos 		(void)NULL;
341b5677b36Schristos 	if (last == NULL)
342b5677b36Schristos 		*rules = new;
343b5677b36Schristos 	else
344b5677b36Schristos 		last->next = new;
345b5677b36Schristos 
346b5677b36Schristos 	/* Try to instantiate map accessors for this if necessary & approp. */
347b5677b36Schristos 	inst = &irs->accessors[acc];
348b5677b36Schristos 	if (inst->acc == NULL && accs[acc] != NULL)
349b5677b36Schristos 		inst->acc = (*accs[acc])(irs->options);
350b5677b36Schristos 	if (inst->acc != NULL) {
351b5677b36Schristos 		if (inst->gr == NULL && inst->acc->gr_map != NULL)
352b5677b36Schristos 			inst->gr = (*inst->acc->gr_map)(inst->acc);
353b5677b36Schristos 		if (inst->pw == NULL && inst->acc->pw_map != NULL)
354b5677b36Schristos 			inst->pw = (*inst->acc->pw_map)(inst->acc);
355b5677b36Schristos 		if (inst->sv == NULL && inst->acc->sv_map != NULL)
356b5677b36Schristos 			inst->sv = (*inst->acc->sv_map)(inst->acc);
357b5677b36Schristos 		if (inst->pr == NULL && inst->acc->pr_map != NULL)
358b5677b36Schristos 			inst->pr = (*inst->acc->pr_map)(inst->acc);
359b5677b36Schristos 		if (inst->ho == NULL && inst->acc->ho_map != NULL)
360b5677b36Schristos 			inst->ho = (*inst->acc->ho_map)(inst->acc);
361b5677b36Schristos 		if (inst->nw == NULL && inst->acc->nw_map != NULL)
362b5677b36Schristos 			inst->nw = (*inst->acc->nw_map)(inst->acc);
363b5677b36Schristos 		if (inst->ng == NULL && inst->acc->ng_map != NULL)
364b5677b36Schristos 			inst->ng = (*inst->acc->ng_map)(inst->acc);
365b5677b36Schristos 	}
366b5677b36Schristos 
367b5677b36Schristos 	return (0);
368b5677b36Schristos }
369b5677b36Schristos 
370b5677b36Schristos static void
default_map_rules(struct gen_p * irs)371b5677b36Schristos default_map_rules(struct gen_p *irs) {
372b5677b36Schristos 	/* Install time honoured and proved BSD style rules as default. */
373b5677b36Schristos 	add_rule(irs, irs_gr, irs_lcl, "");
374b5677b36Schristos 	add_rule(irs, irs_pw, irs_lcl, "");
375b5677b36Schristos 	add_rule(irs, irs_sv, irs_lcl, "");
376b5677b36Schristos 	add_rule(irs, irs_pr, irs_lcl, "");
377b5677b36Schristos 	add_rule(irs, irs_ho, irs_dns, "continue");
378b5677b36Schristos 	add_rule(irs, irs_ho, irs_lcl, "");
379b5677b36Schristos 	add_rule(irs, irs_nw, irs_dns, "continue");
380b5677b36Schristos 	add_rule(irs, irs_nw, irs_lcl, "");
381b5677b36Schristos 	add_rule(irs, irs_ng, irs_lcl, "");
382b5677b36Schristos }
383b5677b36Schristos 
384b5677b36Schristos static void
init_map_rules(struct gen_p * irs,const char * conf_file)385b5677b36Schristos init_map_rules(struct gen_p *irs, const char *conf_file) {
386b5677b36Schristos 	char line[1024], pattern[40], mapname[20], accname[20], options[100];
387b5677b36Schristos 	FILE *conf;
388b5677b36Schristos 
389b5677b36Schristos 	if (conf_file == NULL)
390b5677b36Schristos 		conf_file = _PATH_IRS_CONF ;
391b5677b36Schristos 
392b5677b36Schristos 	/* A conf file of "" means compiled in defaults. Irpd wants this */
393b5677b36Schristos 	if (conf_file[0] == '\0' || (conf = fopen(conf_file, "r")) == NULL) {
394b5677b36Schristos 		default_map_rules(irs);
395b5677b36Schristos 		return;
396b5677b36Schristos 	}
397b5677b36Schristos 	(void) sprintf(pattern, "%%%lus %%%lus %%%lus\n",
398b5677b36Schristos 		       (unsigned long)sizeof mapname,
399b5677b36Schristos 		       (unsigned long)sizeof accname,
400b5677b36Schristos 		       (unsigned long)sizeof options);
401b5677b36Schristos 	while (fgets(line, sizeof line, conf)) {
402b5677b36Schristos 		enum irs_map_id map;
403b5677b36Schristos 		enum irs_acc_id acc;
404b5677b36Schristos 		char *tmp;
405b5677b36Schristos 		int n;
406b5677b36Schristos 
407b5677b36Schristos 		for (tmp = line;
408b5677b36Schristos 		     isascii((unsigned char)*tmp) &&
409b5677b36Schristos 		     isspace((unsigned char)*tmp);
410b5677b36Schristos 		     tmp++)
411b5677b36Schristos 			(void)NULL;
412b5677b36Schristos 		if (*tmp == '#' || *tmp == '\n' || *tmp == '\0')
413b5677b36Schristos 			continue;
414b5677b36Schristos 		n = sscanf(tmp, pattern, mapname, accname, options);
415b5677b36Schristos 		if (n < 2)
416b5677b36Schristos 			continue;
417b5677b36Schristos 		if (n < 3)
418b5677b36Schristos 			options[0] = '\0';
419b5677b36Schristos 
420b5677b36Schristos 		n = find_name(mapname, map_names);
421b5677b36Schristos 		INSIST(n < irs_nmap);
422b5677b36Schristos 		if (n < 0)
423b5677b36Schristos 			continue;
424b5677b36Schristos 		map = (enum irs_map_id) n;
425b5677b36Schristos 
426b5677b36Schristos 		n = find_name(accname, acc_names);
427b5677b36Schristos 		INSIST(n < irs_nacc);
428b5677b36Schristos 		if (n < 0)
429b5677b36Schristos 			continue;
430b5677b36Schristos 		acc = (enum irs_acc_id) n;
431b5677b36Schristos 
432b5677b36Schristos 		add_rule(irs, map, acc, options);
433b5677b36Schristos 	}
434b5677b36Schristos 	fclose(conf);
435b5677b36Schristos }
436