xref: /minix3/sbin/ifconfig/parse.c (revision 90b801219a391518dca4b04b17c88ad3b82b6ad9)
1*90b80121SDavid van Moolenbroek /*	$NetBSD: parse.c,v 1.18 2013/07/17 15:42:03 christos Exp $	*/
2*90b80121SDavid van Moolenbroek 
3*90b80121SDavid van Moolenbroek /*-
4*90b80121SDavid van Moolenbroek  * Copyright (c) 2008 David Young.  All rights reserved.
5*90b80121SDavid van Moolenbroek  *
6*90b80121SDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
7*90b80121SDavid van Moolenbroek  * modification, are permitted provided that the following conditions
8*90b80121SDavid van Moolenbroek  * are met:
9*90b80121SDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
10*90b80121SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
11*90b80121SDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
12*90b80121SDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
13*90b80121SDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
14*90b80121SDavid van Moolenbroek  *
15*90b80121SDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16*90b80121SDavid van Moolenbroek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17*90b80121SDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18*90b80121SDavid van Moolenbroek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19*90b80121SDavid van Moolenbroek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20*90b80121SDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21*90b80121SDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22*90b80121SDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23*90b80121SDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24*90b80121SDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25*90b80121SDavid van Moolenbroek  * SUCH DAMAGE.
26*90b80121SDavid van Moolenbroek  */
27*90b80121SDavid van Moolenbroek 
28*90b80121SDavid van Moolenbroek #include <sys/cdefs.h>
29*90b80121SDavid van Moolenbroek #ifndef lint
30*90b80121SDavid van Moolenbroek __RCSID("$NetBSD: parse.c,v 1.18 2013/07/17 15:42:03 christos Exp $");
31*90b80121SDavid van Moolenbroek #endif /* not lint */
32*90b80121SDavid van Moolenbroek 
33*90b80121SDavid van Moolenbroek #include <err.h>
34*90b80121SDavid van Moolenbroek #include <errno.h>
35*90b80121SDavid van Moolenbroek #include <limits.h>
36*90b80121SDavid van Moolenbroek #include <netdb.h>
37*90b80121SDavid van Moolenbroek #include <stddef.h>
38*90b80121SDavid van Moolenbroek #include <stdio.h>
39*90b80121SDavid van Moolenbroek #include <stdlib.h>
40*90b80121SDavid van Moolenbroek #include <string.h>
41*90b80121SDavid van Moolenbroek 
42*90b80121SDavid van Moolenbroek #include <arpa/inet.h>
43*90b80121SDavid van Moolenbroek #include <sys/param.h>
44*90b80121SDavid van Moolenbroek #include <net/if.h>
45*90b80121SDavid van Moolenbroek #include <net/if_dl.h>
46*90b80121SDavid van Moolenbroek #include <netatalk/at.h>
47*90b80121SDavid van Moolenbroek 
48*90b80121SDavid van Moolenbroek #include "env.h"
49*90b80121SDavid van Moolenbroek #include "parse.h"
50*90b80121SDavid van Moolenbroek #include "util.h"
51*90b80121SDavid van Moolenbroek 
52*90b80121SDavid van Moolenbroek #ifdef DEBUG
53*90b80121SDavid van Moolenbroek #define dbg_warnx(__fmt, ...)	warnx(__fmt, __VA_ARGS__)
54*90b80121SDavid van Moolenbroek #else
55*90b80121SDavid van Moolenbroek #define dbg_warnx(__fmt, ...)	/* empty */
56*90b80121SDavid van Moolenbroek #endif
57*90b80121SDavid van Moolenbroek 
58*90b80121SDavid van Moolenbroek static int parser_default_init(struct parser *);
59*90b80121SDavid van Moolenbroek static int pbranch_init(struct parser *);
60*90b80121SDavid van Moolenbroek static int pkw_init(struct parser *);
61*90b80121SDavid van Moolenbroek 
62*90b80121SDavid van Moolenbroek static int pterm_match(const struct parser *, const struct match *,
63*90b80121SDavid van Moolenbroek     struct match *, int, const char *);
64*90b80121SDavid van Moolenbroek 
65*90b80121SDavid van Moolenbroek static int paddr_match(const struct parser *, const struct match *,
66*90b80121SDavid van Moolenbroek     struct match *, int, const char *);
67*90b80121SDavid van Moolenbroek 
68*90b80121SDavid van Moolenbroek static int pbranch_match(const struct parser *, const struct match *,
69*90b80121SDavid van Moolenbroek     struct match *, int, const char *);
70*90b80121SDavid van Moolenbroek 
71*90b80121SDavid van Moolenbroek static int piface_match(const struct parser *, const struct match *,
72*90b80121SDavid van Moolenbroek     struct match *, int, const char *);
73*90b80121SDavid van Moolenbroek 
74*90b80121SDavid van Moolenbroek static int pstr_match(const struct parser *, const struct match *,
75*90b80121SDavid van Moolenbroek     struct match *, int, const char *);
76*90b80121SDavid van Moolenbroek 
77*90b80121SDavid van Moolenbroek static int pinteger_match(const struct parser *, const struct match *,
78*90b80121SDavid van Moolenbroek     struct match *, int, const char *);
79*90b80121SDavid van Moolenbroek 
80*90b80121SDavid van Moolenbroek static int pkw_match(const struct parser *, const struct match *,
81*90b80121SDavid van Moolenbroek     struct match *, int, const char *);
82*90b80121SDavid van Moolenbroek 
83*90b80121SDavid van Moolenbroek const struct parser_methods pterm_methods = {
84*90b80121SDavid van Moolenbroek 	  .pm_match = pterm_match
85*90b80121SDavid van Moolenbroek 	, .pm_init = NULL
86*90b80121SDavid van Moolenbroek };
87*90b80121SDavid van Moolenbroek 
88*90b80121SDavid van Moolenbroek const struct parser_methods pstr_methods = {
89*90b80121SDavid van Moolenbroek 	  .pm_match = pstr_match
90*90b80121SDavid van Moolenbroek 	, .pm_init = parser_default_init
91*90b80121SDavid van Moolenbroek };
92*90b80121SDavid van Moolenbroek 
93*90b80121SDavid van Moolenbroek const struct parser_methods pinteger_methods = {
94*90b80121SDavid van Moolenbroek 	  .pm_match = pinteger_match
95*90b80121SDavid van Moolenbroek 	, .pm_init = parser_default_init
96*90b80121SDavid van Moolenbroek };
97*90b80121SDavid van Moolenbroek 
98*90b80121SDavid van Moolenbroek const struct parser_methods paddr_methods = {
99*90b80121SDavid van Moolenbroek 	  .pm_match = paddr_match
100*90b80121SDavid van Moolenbroek 	, .pm_init = parser_default_init
101*90b80121SDavid van Moolenbroek };
102*90b80121SDavid van Moolenbroek 
103*90b80121SDavid van Moolenbroek const struct parser_methods piface_methods = {
104*90b80121SDavid van Moolenbroek 	  .pm_match = piface_match
105*90b80121SDavid van Moolenbroek 	, .pm_init = parser_default_init
106*90b80121SDavid van Moolenbroek };
107*90b80121SDavid van Moolenbroek 
108*90b80121SDavid van Moolenbroek const struct parser_methods pbranch_methods = {
109*90b80121SDavid van Moolenbroek 	  .pm_match = pbranch_match
110*90b80121SDavid van Moolenbroek 	, .pm_init = pbranch_init
111*90b80121SDavid van Moolenbroek };
112*90b80121SDavid van Moolenbroek 
113*90b80121SDavid van Moolenbroek const struct parser_methods pkw_methods = {
114*90b80121SDavid van Moolenbroek 	  .pm_match = pkw_match
115*90b80121SDavid van Moolenbroek 	, .pm_init = pkw_init
116*90b80121SDavid van Moolenbroek };
117*90b80121SDavid van Moolenbroek 
118*90b80121SDavid van Moolenbroek static int
match_setenv(const struct match * im,struct match * om,const char * key,prop_object_t o)119*90b80121SDavid van Moolenbroek match_setenv(const struct match *im, struct match *om, const char *key,
120*90b80121SDavid van Moolenbroek     prop_object_t o)
121*90b80121SDavid van Moolenbroek {
122*90b80121SDavid van Moolenbroek 	if (im == NULL)
123*90b80121SDavid van Moolenbroek 		om->m_env = prop_dictionary_create();
124*90b80121SDavid van Moolenbroek 	else
125*90b80121SDavid van Moolenbroek 		om->m_env = prop_dictionary_copy(im->m_env);
126*90b80121SDavid van Moolenbroek 
127*90b80121SDavid van Moolenbroek 	if (om->m_env == NULL)
128*90b80121SDavid van Moolenbroek 		goto delobj;
129*90b80121SDavid van Moolenbroek 
130*90b80121SDavid van Moolenbroek 	if (key != NULL && !prop_dictionary_set(om->m_env, key, o))
131*90b80121SDavid van Moolenbroek 		goto deldict;
132*90b80121SDavid van Moolenbroek 
133*90b80121SDavid van Moolenbroek 	if (o != NULL)
134*90b80121SDavid van Moolenbroek 		prop_object_release((prop_object_t)o);
135*90b80121SDavid van Moolenbroek 
136*90b80121SDavid van Moolenbroek 	return 0;
137*90b80121SDavid van Moolenbroek deldict:
138*90b80121SDavid van Moolenbroek 	prop_object_release((prop_object_t)om->m_env);
139*90b80121SDavid van Moolenbroek 	om->m_env = NULL;
140*90b80121SDavid van Moolenbroek delobj:
141*90b80121SDavid van Moolenbroek 	prop_object_release((prop_object_t)o);
142*90b80121SDavid van Moolenbroek 	errno = ENOMEM;
143*90b80121SDavid van Moolenbroek 	return -1;
144*90b80121SDavid van Moolenbroek }
145*90b80121SDavid van Moolenbroek 
146*90b80121SDavid van Moolenbroek int
pstr_match(const struct parser * p,const struct match * im,struct match * om,int argidx,const char * arg)147*90b80121SDavid van Moolenbroek pstr_match(const struct parser *p, const struct match *im, struct match *om,
148*90b80121SDavid van Moolenbroek     int argidx, const char *arg)
149*90b80121SDavid van Moolenbroek {
150*90b80121SDavid van Moolenbroek 	prop_object_t o;
151*90b80121SDavid van Moolenbroek 	const struct pstr *ps = (const struct pstr *)p;
152*90b80121SDavid van Moolenbroek 	uint8_t buf[128];
153*90b80121SDavid van Moolenbroek 	int len;
154*90b80121SDavid van Moolenbroek 
155*90b80121SDavid van Moolenbroek 	if (arg == NULL) {
156*90b80121SDavid van Moolenbroek 		errno = EINVAL;
157*90b80121SDavid van Moolenbroek 		return -1;
158*90b80121SDavid van Moolenbroek 	}
159*90b80121SDavid van Moolenbroek 
160*90b80121SDavid van Moolenbroek 	len = (int)sizeof(buf);
161*90b80121SDavid van Moolenbroek 	if (get_string(arg, NULL, buf, &len, ps->ps_hexok) == NULL) {
162*90b80121SDavid van Moolenbroek 		errno = EINVAL;
163*90b80121SDavid van Moolenbroek 		return -1;
164*90b80121SDavid van Moolenbroek 	}
165*90b80121SDavid van Moolenbroek 
166*90b80121SDavid van Moolenbroek 	o = (prop_object_t)prop_data_create_data(buf, len);
167*90b80121SDavid van Moolenbroek 
168*90b80121SDavid van Moolenbroek 	if (o == NULL) {
169*90b80121SDavid van Moolenbroek 		errno = ENOMEM;
170*90b80121SDavid van Moolenbroek 		return -1;
171*90b80121SDavid van Moolenbroek 	}
172*90b80121SDavid van Moolenbroek 
173*90b80121SDavid van Moolenbroek 	if (match_setenv(im, om, ps->ps_key, o) == -1)
174*90b80121SDavid van Moolenbroek 		return -1;
175*90b80121SDavid van Moolenbroek 
176*90b80121SDavid van Moolenbroek 	om->m_argidx = argidx;
177*90b80121SDavid van Moolenbroek 	om->m_parser = p;
178*90b80121SDavid van Moolenbroek 	om->m_nextparser = p->p_nextparser;
179*90b80121SDavid van Moolenbroek 
180*90b80121SDavid van Moolenbroek 	return 0;
181*90b80121SDavid van Moolenbroek }
182*90b80121SDavid van Moolenbroek 
183*90b80121SDavid van Moolenbroek int
pinteger_match(const struct parser * p,const struct match * im,struct match * om,int argidx,const char * arg)184*90b80121SDavid van Moolenbroek pinteger_match(const struct parser *p, const struct match *im, struct match *om,
185*90b80121SDavid van Moolenbroek     int argidx, const char *arg)
186*90b80121SDavid van Moolenbroek {
187*90b80121SDavid van Moolenbroek 	prop_object_t o;
188*90b80121SDavid van Moolenbroek 	const struct pinteger *pi = (const struct pinteger *)p;
189*90b80121SDavid van Moolenbroek 	char *end;
190*90b80121SDavid van Moolenbroek 	int64_t val;
191*90b80121SDavid van Moolenbroek 
192*90b80121SDavid van Moolenbroek 	if (arg == NULL) {
193*90b80121SDavid van Moolenbroek 		errno = EINVAL;
194*90b80121SDavid van Moolenbroek 		return -1;
195*90b80121SDavid van Moolenbroek 	}
196*90b80121SDavid van Moolenbroek 
197*90b80121SDavid van Moolenbroek 	val = strtoimax(arg, &end, pi->pi_base);
198*90b80121SDavid van Moolenbroek 	if ((val == INTMAX_MIN || val == INTMAX_MAX) && errno == ERANGE)
199*90b80121SDavid van Moolenbroek 		return -1;
200*90b80121SDavid van Moolenbroek 
201*90b80121SDavid van Moolenbroek 	if (*end != '\0') {
202*90b80121SDavid van Moolenbroek 		errno = EINVAL;
203*90b80121SDavid van Moolenbroek 		return -1;
204*90b80121SDavid van Moolenbroek 	}
205*90b80121SDavid van Moolenbroek 
206*90b80121SDavid van Moolenbroek 	if (val < pi->pi_min || val > pi->pi_max) {
207*90b80121SDavid van Moolenbroek 		errno = ERANGE;
208*90b80121SDavid van Moolenbroek 		return -1;
209*90b80121SDavid van Moolenbroek 	}
210*90b80121SDavid van Moolenbroek 
211*90b80121SDavid van Moolenbroek 	o = (prop_object_t)prop_number_create_integer(val);
212*90b80121SDavid van Moolenbroek 
213*90b80121SDavid van Moolenbroek 	if (o == NULL) {
214*90b80121SDavid van Moolenbroek 		errno = ENOMEM;
215*90b80121SDavid van Moolenbroek 		return -1;
216*90b80121SDavid van Moolenbroek 	}
217*90b80121SDavid van Moolenbroek 
218*90b80121SDavid van Moolenbroek 	if (match_setenv(im, om, pi->pi_key, o) == -1)
219*90b80121SDavid van Moolenbroek 		return -1;
220*90b80121SDavid van Moolenbroek 
221*90b80121SDavid van Moolenbroek 	om->m_argidx = argidx;
222*90b80121SDavid van Moolenbroek 	om->m_parser = p;
223*90b80121SDavid van Moolenbroek 	om->m_nextparser = p->p_nextparser;
224*90b80121SDavid van Moolenbroek 
225*90b80121SDavid van Moolenbroek 	return 0;
226*90b80121SDavid van Moolenbroek }
227*90b80121SDavid van Moolenbroek 
228*90b80121SDavid van Moolenbroek static int
parse_linkaddr(const char * addr,struct sockaddr_storage * ss)229*90b80121SDavid van Moolenbroek parse_linkaddr(const char *addr, struct sockaddr_storage *ss)
230*90b80121SDavid van Moolenbroek {
231*90b80121SDavid van Moolenbroek 	static const size_t maxlen =
232*90b80121SDavid van Moolenbroek 	    sizeof(*ss) - offsetof(struct sockaddr_dl, sdl_data[0]);
233*90b80121SDavid van Moolenbroek 	enum {
234*90b80121SDavid van Moolenbroek 		LLADDR_S_INITIAL = 0,
235*90b80121SDavid van Moolenbroek 		LLADDR_S_ONE_OCTET = 1,
236*90b80121SDavid van Moolenbroek 		LLADDR_S_TWO_OCTETS = 2,
237*90b80121SDavid van Moolenbroek 		LLADDR_S_COLON = 3
238*90b80121SDavid van Moolenbroek 	} state = LLADDR_S_INITIAL;
239*90b80121SDavid van Moolenbroek 	uint8_t octet = 0, val;
240*90b80121SDavid van Moolenbroek 	struct sockaddr_dl *sdl;
241*90b80121SDavid van Moolenbroek 	const char *p;
242*90b80121SDavid van Moolenbroek 	size_t i;
243*90b80121SDavid van Moolenbroek 
244*90b80121SDavid van Moolenbroek 	memset(ss, 0, sizeof(*ss));
245*90b80121SDavid van Moolenbroek 	ss->ss_family = AF_LINK;
246*90b80121SDavid van Moolenbroek 	sdl = (struct sockaddr_dl *)ss;
247*90b80121SDavid van Moolenbroek 
248*90b80121SDavid van Moolenbroek 	for (i = 0, p = addr; i < maxlen; p++) {
249*90b80121SDavid van Moolenbroek 		dbg_warnx("%s.%d: *p == %c, state %d", __func__, __LINE__, *p,
250*90b80121SDavid van Moolenbroek 		    state);
251*90b80121SDavid van Moolenbroek 		if (*p == '\0') {
252*90b80121SDavid van Moolenbroek 			dbg_warnx("%s.%d", __func__, __LINE__);
253*90b80121SDavid van Moolenbroek 			if (state != LLADDR_S_ONE_OCTET &&
254*90b80121SDavid van Moolenbroek 			    state != LLADDR_S_TWO_OCTETS)
255*90b80121SDavid van Moolenbroek 				return -1;
256*90b80121SDavid van Moolenbroek 			dbg_warnx("%s.%d", __func__, __LINE__);
257*90b80121SDavid van Moolenbroek 			sdl->sdl_data[i++] = octet;
258*90b80121SDavid van Moolenbroek 			sdl->sdl_len = offsetof(struct sockaddr_dl, sdl_data)
259*90b80121SDavid van Moolenbroek 			    + i * sizeof(sdl->sdl_data[0]);
260*90b80121SDavid van Moolenbroek 			sdl->sdl_alen = i;
261*90b80121SDavid van Moolenbroek 			return 0;
262*90b80121SDavid van Moolenbroek 		}
263*90b80121SDavid van Moolenbroek 		if (*p == ':') {
264*90b80121SDavid van Moolenbroek 			dbg_warnx("%s.%d", __func__, __LINE__);
265*90b80121SDavid van Moolenbroek 			if (state != LLADDR_S_ONE_OCTET &&
266*90b80121SDavid van Moolenbroek 			    state != LLADDR_S_TWO_OCTETS)
267*90b80121SDavid van Moolenbroek 				return -1;
268*90b80121SDavid van Moolenbroek 			dbg_warnx("%s.%d", __func__, __LINE__);
269*90b80121SDavid van Moolenbroek 			sdl->sdl_data[i++] = octet;
270*90b80121SDavid van Moolenbroek 			state = LLADDR_S_COLON;
271*90b80121SDavid van Moolenbroek 			continue;
272*90b80121SDavid van Moolenbroek 		}
273*90b80121SDavid van Moolenbroek 		if ('a' <= *p && *p <= 'f')
274*90b80121SDavid van Moolenbroek 			val = 10 + *p - 'a';
275*90b80121SDavid van Moolenbroek 		else if ('A' <= *p && *p <= 'F')
276*90b80121SDavid van Moolenbroek 			val = 10 + *p - 'A';
277*90b80121SDavid van Moolenbroek 		else if ('0' <= *p && *p <= '9')
278*90b80121SDavid van Moolenbroek 			val = *p - '0';
279*90b80121SDavid van Moolenbroek 		else
280*90b80121SDavid van Moolenbroek 			return -1;
281*90b80121SDavid van Moolenbroek 
282*90b80121SDavid van Moolenbroek 		dbg_warnx("%s.%d", __func__, __LINE__);
283*90b80121SDavid van Moolenbroek 		if (state == LLADDR_S_ONE_OCTET) {
284*90b80121SDavid van Moolenbroek 			state = LLADDR_S_TWO_OCTETS;
285*90b80121SDavid van Moolenbroek 			octet <<= 4;
286*90b80121SDavid van Moolenbroek 			octet |= val;
287*90b80121SDavid van Moolenbroek 		} else if (state != LLADDR_S_INITIAL && state != LLADDR_S_COLON)
288*90b80121SDavid van Moolenbroek 			return -1;
289*90b80121SDavid van Moolenbroek 		else {
290*90b80121SDavid van Moolenbroek 			state = LLADDR_S_ONE_OCTET;
291*90b80121SDavid van Moolenbroek 			octet = val;
292*90b80121SDavid van Moolenbroek 		}
293*90b80121SDavid van Moolenbroek 		dbg_warnx("%s.%d", __func__, __LINE__);
294*90b80121SDavid van Moolenbroek 	}
295*90b80121SDavid van Moolenbroek 	return -1;
296*90b80121SDavid van Moolenbroek }
297*90b80121SDavid van Moolenbroek 
298*90b80121SDavid van Moolenbroek static int
paddr_match(const struct parser * p,const struct match * im,struct match * om,int argidx,const char * arg0)299*90b80121SDavid van Moolenbroek paddr_match(const struct parser *p, const struct match *im, struct match *om,
300*90b80121SDavid van Moolenbroek     int argidx, const char *arg0)
301*90b80121SDavid van Moolenbroek {
302*90b80121SDavid van Moolenbroek 	unsigned int net, node;
303*90b80121SDavid van Moolenbroek 	int nread;
304*90b80121SDavid van Moolenbroek 	union {
305*90b80121SDavid van Moolenbroek 		struct sockaddr sa;
306*90b80121SDavid van Moolenbroek 		struct sockaddr_at sat;
307*90b80121SDavid van Moolenbroek 		struct sockaddr_in sin;
308*90b80121SDavid van Moolenbroek 		struct sockaddr_storage ss;
309*90b80121SDavid van Moolenbroek 	} u;
310*90b80121SDavid van Moolenbroek 	const struct paddr *pa = (const struct paddr *)p;
311*90b80121SDavid van Moolenbroek 	prop_data_t d;
312*90b80121SDavid van Moolenbroek 	prop_object_t o;
313*90b80121SDavid van Moolenbroek 	int64_t af0;
314*90b80121SDavid van Moolenbroek 	int af, rc;
315*90b80121SDavid van Moolenbroek 	struct paddr_prefix *pfx, *mask;
316*90b80121SDavid van Moolenbroek 	const struct sockaddr *sa = NULL;
317*90b80121SDavid van Moolenbroek 	struct addrinfo hints, *result = NULL;
318*90b80121SDavid van Moolenbroek 	char *arg, *end, *plen = NULL, *servname0;
319*90b80121SDavid van Moolenbroek 	const char *servname;
320*90b80121SDavid van Moolenbroek 	long prefixlen = -1;
321*90b80121SDavid van Moolenbroek 	size_t len;
322*90b80121SDavid van Moolenbroek 
323*90b80121SDavid van Moolenbroek 	if (arg0 == NULL) {
324*90b80121SDavid van Moolenbroek 		errno = EINVAL;
325*90b80121SDavid van Moolenbroek 		return -1;
326*90b80121SDavid van Moolenbroek 	}
327*90b80121SDavid van Moolenbroek 
328*90b80121SDavid van Moolenbroek 	if (pa->pa_activator != NULL &&
329*90b80121SDavid van Moolenbroek 	    prop_dictionary_get(im->m_env, pa->pa_activator) == NULL)
330*90b80121SDavid van Moolenbroek 		return -1;
331*90b80121SDavid van Moolenbroek 
332*90b80121SDavid van Moolenbroek 	if (pa->pa_deactivator != NULL &&
333*90b80121SDavid van Moolenbroek 	    prop_dictionary_get(im->m_env, pa->pa_deactivator) != NULL)
334*90b80121SDavid van Moolenbroek 		return -1;
335*90b80121SDavid van Moolenbroek 
336*90b80121SDavid van Moolenbroek 	if (!prop_dictionary_get_int64(im->m_env, "af", &af0))
337*90b80121SDavid van Moolenbroek 		af = AF_UNSPEC;
338*90b80121SDavid van Moolenbroek 	else
339*90b80121SDavid van Moolenbroek 		af = af0;
340*90b80121SDavid van Moolenbroek 
341*90b80121SDavid van Moolenbroek 	memset(&u, 0, sizeof(u));
342*90b80121SDavid van Moolenbroek 
343*90b80121SDavid van Moolenbroek 	switch (af) {
344*90b80121SDavid van Moolenbroek 	case AF_UNSPEC:
345*90b80121SDavid van Moolenbroek 	case AF_INET:
346*90b80121SDavid van Moolenbroek 	case AF_INET6:
347*90b80121SDavid van Moolenbroek 		if ((arg = strdup(arg0)) == NULL)
348*90b80121SDavid van Moolenbroek 			return -1;
349*90b80121SDavid van Moolenbroek 
350*90b80121SDavid van Moolenbroek 		servname0 = arg;
351*90b80121SDavid van Moolenbroek 		(void)strsep(&servname0, ",");
352*90b80121SDavid van Moolenbroek 		servname = (servname0 == NULL) ? "0" : servname0;
353*90b80121SDavid van Moolenbroek 
354*90b80121SDavid van Moolenbroek 		if (pa->pa_maskkey == NULL)
355*90b80121SDavid van Moolenbroek 			;
356*90b80121SDavid van Moolenbroek 		else if ((plen = strrchr(arg, '/')) != NULL)
357*90b80121SDavid van Moolenbroek 			*plen++ = '\0';
358*90b80121SDavid van Moolenbroek 
359*90b80121SDavid van Moolenbroek 		memset(&hints, 0, sizeof(hints));
360*90b80121SDavid van Moolenbroek 
361*90b80121SDavid van Moolenbroek 		hints.ai_flags = AI_NUMERICHOST | AI_PASSIVE;
362*90b80121SDavid van Moolenbroek 		hints.ai_family = af;
363*90b80121SDavid van Moolenbroek 		hints.ai_socktype = SOCK_DGRAM;
364*90b80121SDavid van Moolenbroek 
365*90b80121SDavid van Moolenbroek 		for (;;) {
366*90b80121SDavid van Moolenbroek 			rc = getaddrinfo(arg, servname, &hints, &result);
367*90b80121SDavid van Moolenbroek 			if (rc == 0) {
368*90b80121SDavid van Moolenbroek 				if (result->ai_next == NULL)
369*90b80121SDavid van Moolenbroek 					sa = result->ai_addr;
370*90b80121SDavid van Moolenbroek 				else
371*90b80121SDavid van Moolenbroek 					errno = EMLINK;
372*90b80121SDavid van Moolenbroek 				break;
373*90b80121SDavid van Moolenbroek 			} else if ((hints.ai_flags & AI_NUMERICHOST) != 0 &&
374*90b80121SDavid van Moolenbroek 			    (af == AF_INET || af == AF_UNSPEC) &&
375*90b80121SDavid van Moolenbroek 			    inet_aton(arg, &u.sin.sin_addr) == 1) {
376*90b80121SDavid van Moolenbroek 				u.sin.sin_family = AF_INET;
377*90b80121SDavid van Moolenbroek 				u.sin.sin_len = sizeof(u.sin);
378*90b80121SDavid van Moolenbroek 				sa = &u.sa;
379*90b80121SDavid van Moolenbroek 				break;
380*90b80121SDavid van Moolenbroek 			} else if ((hints.ai_flags & AI_NUMERICHOST) == 0 ||
381*90b80121SDavid van Moolenbroek 				 rc != EAI_NONAME) {
382*90b80121SDavid van Moolenbroek 				errno = ENOENT;
383*90b80121SDavid van Moolenbroek 				break;
384*90b80121SDavid van Moolenbroek 			}
385*90b80121SDavid van Moolenbroek 			hints.ai_flags &= ~AI_NUMERICHOST;
386*90b80121SDavid van Moolenbroek 		}
387*90b80121SDavid van Moolenbroek 
388*90b80121SDavid van Moolenbroek 
389*90b80121SDavid van Moolenbroek 		if (plen == NULL)
390*90b80121SDavid van Moolenbroek 			prefixlen = -1;
391*90b80121SDavid van Moolenbroek 		else {
392*90b80121SDavid van Moolenbroek 			prefixlen = strtol(plen, &end, 10);
393*90b80121SDavid van Moolenbroek 			if (end != NULL && *end != '\0')
394*90b80121SDavid van Moolenbroek 				sa = NULL;
395*90b80121SDavid van Moolenbroek 			if (prefixlen < 0 || prefixlen >= UINT8_MAX) {
396*90b80121SDavid van Moolenbroek 				errno = ERANGE;
397*90b80121SDavid van Moolenbroek 				sa = NULL;
398*90b80121SDavid van Moolenbroek 			}
399*90b80121SDavid van Moolenbroek 		}
400*90b80121SDavid van Moolenbroek 
401*90b80121SDavid van Moolenbroek 		free(arg);
402*90b80121SDavid van Moolenbroek 		if (sa != NULL || af != AF_UNSPEC)
403*90b80121SDavid van Moolenbroek 			break;
404*90b80121SDavid van Moolenbroek 		/*FALLTHROUGH*/
405*90b80121SDavid van Moolenbroek 	case AF_APPLETALK:
406*90b80121SDavid van Moolenbroek 		if (sscanf(arg0, "%u.%u%n", &net, &node, &nread) == 2 &&
407*90b80121SDavid van Moolenbroek 		    net != 0 && net <= 0xffff && node != 0 && node <= 0xfe &&
408*90b80121SDavid van Moolenbroek 		    arg0[nread] == '\0') {
409*90b80121SDavid van Moolenbroek 			u.sat.sat_family = AF_APPLETALK;
410*90b80121SDavid van Moolenbroek 			u.sat.sat_len = sizeof(u.sat);
411*90b80121SDavid van Moolenbroek 			u.sat.sat_addr.s_net = htons(net);
412*90b80121SDavid van Moolenbroek 			u.sat.sat_addr.s_node = node;
413*90b80121SDavid van Moolenbroek 			sa = &u.sa;
414*90b80121SDavid van Moolenbroek 		}
415*90b80121SDavid van Moolenbroek 		break;
416*90b80121SDavid van Moolenbroek 	case AF_LINK:
417*90b80121SDavid van Moolenbroek 		if (parse_linkaddr(arg0, &u.ss) == -1)
418*90b80121SDavid van Moolenbroek 			sa = NULL;
419*90b80121SDavid van Moolenbroek 		else
420*90b80121SDavid van Moolenbroek 			sa = &u.sa;
421*90b80121SDavid van Moolenbroek 		break;
422*90b80121SDavid van Moolenbroek 	}
423*90b80121SDavid van Moolenbroek 
424*90b80121SDavid van Moolenbroek 	if (sa == NULL)
425*90b80121SDavid van Moolenbroek 		return -1;
426*90b80121SDavid van Moolenbroek 
427*90b80121SDavid van Moolenbroek 	len = offsetof(struct paddr_prefix, pfx_addr) + sa->sa_len;
428*90b80121SDavid van Moolenbroek 
429*90b80121SDavid van Moolenbroek 	if ((pfx = malloc(len)) == NULL)
430*90b80121SDavid van Moolenbroek 		return -1;
431*90b80121SDavid van Moolenbroek 
432*90b80121SDavid van Moolenbroek #if 0
433*90b80121SDavid van Moolenbroek 	{
434*90b80121SDavid van Moolenbroek 		int i;
435*90b80121SDavid van Moolenbroek 
436*90b80121SDavid van Moolenbroek 		for (i = 0; i < sa->sa_len; i++)
437*90b80121SDavid van Moolenbroek 			printf(" %02x", ((const uint8_t *)sa)[i]);
438*90b80121SDavid van Moolenbroek 		printf("\n");
439*90b80121SDavid van Moolenbroek 	}
440*90b80121SDavid van Moolenbroek #endif
441*90b80121SDavid van Moolenbroek 
442*90b80121SDavid van Moolenbroek 	pfx->pfx_len = (int16_t)prefixlen;
443*90b80121SDavid van Moolenbroek 	memcpy(&pfx->pfx_addr, sa, sa->sa_len);
444*90b80121SDavid van Moolenbroek 	af = sa->sa_family;
445*90b80121SDavid van Moolenbroek 
446*90b80121SDavid van Moolenbroek 	if (result != NULL)
447*90b80121SDavid van Moolenbroek 		freeaddrinfo(result);
448*90b80121SDavid van Moolenbroek 
449*90b80121SDavid van Moolenbroek 	o = (prop_object_t)prop_data_create_data(pfx, len);
450*90b80121SDavid van Moolenbroek 
451*90b80121SDavid van Moolenbroek 	free(pfx);
452*90b80121SDavid van Moolenbroek 
453*90b80121SDavid van Moolenbroek 	if (o == NULL)
454*90b80121SDavid van Moolenbroek 		return -1;
455*90b80121SDavid van Moolenbroek 
456*90b80121SDavid van Moolenbroek 	if (match_setenv(im, om, pa->pa_addrkey, o) == -1)
457*90b80121SDavid van Moolenbroek 		return -1;
458*90b80121SDavid van Moolenbroek 
459*90b80121SDavid van Moolenbroek 	if (pa->pa_maskkey != NULL && plen != NULL) {
460*90b80121SDavid van Moolenbroek 		size_t masklen;
461*90b80121SDavid van Moolenbroek 
462*90b80121SDavid van Moolenbroek 		if ((mask = prefixlen_to_mask(af, prefixlen)) == NULL) {
463*90b80121SDavid van Moolenbroek 			err(EXIT_FAILURE, "%s: prefixlen_to_mask(%d, %ld)",
464*90b80121SDavid van Moolenbroek 			    __func__, af, prefixlen);
465*90b80121SDavid van Moolenbroek 			return -1;
466*90b80121SDavid van Moolenbroek 		}
467*90b80121SDavid van Moolenbroek 
468*90b80121SDavid van Moolenbroek 		masklen = paddr_prefix_size(mask);
469*90b80121SDavid van Moolenbroek 
470*90b80121SDavid van Moolenbroek 		d = prop_data_create_data(mask, masklen);
471*90b80121SDavid van Moolenbroek 		free(mask);
472*90b80121SDavid van Moolenbroek 
473*90b80121SDavid van Moolenbroek 		if (d == NULL) {
474*90b80121SDavid van Moolenbroek 			err(EXIT_FAILURE, "%s: prop_data_create_data",
475*90b80121SDavid van Moolenbroek 			    __func__);
476*90b80121SDavid van Moolenbroek 			return -1;
477*90b80121SDavid van Moolenbroek 		}
478*90b80121SDavid van Moolenbroek 
479*90b80121SDavid van Moolenbroek 		rc = prop_dictionary_set(om->m_env, pa->pa_maskkey,
480*90b80121SDavid van Moolenbroek 		    (prop_object_t)d) ? 0 : -1;
481*90b80121SDavid van Moolenbroek 
482*90b80121SDavid van Moolenbroek 		prop_object_release((prop_object_t)d);
483*90b80121SDavid van Moolenbroek 
484*90b80121SDavid van Moolenbroek 		if (rc != 0) {
485*90b80121SDavid van Moolenbroek 			err(EXIT_FAILURE, "%s: prop_dictionary_set", __func__);
486*90b80121SDavid van Moolenbroek 			return rc;
487*90b80121SDavid van Moolenbroek 		}
488*90b80121SDavid van Moolenbroek 	}
489*90b80121SDavid van Moolenbroek 
490*90b80121SDavid van Moolenbroek 	om->m_argidx = argidx;
491*90b80121SDavid van Moolenbroek 	om->m_parser = p;
492*90b80121SDavid van Moolenbroek 	om->m_nextparser = p->p_nextparser;
493*90b80121SDavid van Moolenbroek 	return 0;
494*90b80121SDavid van Moolenbroek }
495*90b80121SDavid van Moolenbroek 
496*90b80121SDavid van Moolenbroek static int
pterm_match(const struct parser * p,const struct match * im,struct match * om,int argidx,const char * arg)497*90b80121SDavid van Moolenbroek pterm_match(const struct parser *p, const struct match *im,
498*90b80121SDavid van Moolenbroek     struct match *om, int argidx, const char *arg)
499*90b80121SDavid van Moolenbroek {
500*90b80121SDavid van Moolenbroek 	const struct pterm *pt = (const struct pterm *)p;
501*90b80121SDavid van Moolenbroek 	prop_bool_t b;
502*90b80121SDavid van Moolenbroek 
503*90b80121SDavid van Moolenbroek 	if (arg != NULL) {
504*90b80121SDavid van Moolenbroek 		errno = EINVAL;
505*90b80121SDavid van Moolenbroek 		return -1;
506*90b80121SDavid van Moolenbroek 	}
507*90b80121SDavid van Moolenbroek 	b = prop_bool_create(true);
508*90b80121SDavid van Moolenbroek 
509*90b80121SDavid van Moolenbroek 	if (match_setenv(im, om, pt->pt_key, (prop_object_t)b) == -1)
510*90b80121SDavid van Moolenbroek 		return -1;
511*90b80121SDavid van Moolenbroek 
512*90b80121SDavid van Moolenbroek 	om->m_argidx = argidx;
513*90b80121SDavid van Moolenbroek 	om->m_parser = p;
514*90b80121SDavid van Moolenbroek 	om->m_nextparser = NULL;
515*90b80121SDavid van Moolenbroek 	return 0;
516*90b80121SDavid van Moolenbroek }
517*90b80121SDavid van Moolenbroek 
518*90b80121SDavid van Moolenbroek static int
piface_match(const struct parser * p,const struct match * im,struct match * om,int argidx,const char * arg)519*90b80121SDavid van Moolenbroek piface_match(const struct parser *p, const struct match *im,
520*90b80121SDavid van Moolenbroek     struct match *om, int argidx, const char *arg)
521*90b80121SDavid van Moolenbroek {
522*90b80121SDavid van Moolenbroek 	const struct piface *pif = (const struct piface *)p;
523*90b80121SDavid van Moolenbroek 	prop_object_t o;
524*90b80121SDavid van Moolenbroek 
525*90b80121SDavid van Moolenbroek 	if (arg == NULL || strlen(arg) > IFNAMSIZ) {
526*90b80121SDavid van Moolenbroek 		errno = EINVAL;
527*90b80121SDavid van Moolenbroek 		return -1;
528*90b80121SDavid van Moolenbroek 	}
529*90b80121SDavid van Moolenbroek 
530*90b80121SDavid van Moolenbroek 	if ((o = (prop_object_t)prop_string_create_cstring(arg)) == NULL) {
531*90b80121SDavid van Moolenbroek 		errno = ENOMEM;
532*90b80121SDavid van Moolenbroek 		return -1;
533*90b80121SDavid van Moolenbroek 	}
534*90b80121SDavid van Moolenbroek 
535*90b80121SDavid van Moolenbroek 	if (match_setenv(im, om, pif->pif_key, o) == -1)
536*90b80121SDavid van Moolenbroek 		return -1;
537*90b80121SDavid van Moolenbroek 
538*90b80121SDavid van Moolenbroek 	om->m_argidx = argidx;
539*90b80121SDavid van Moolenbroek 	om->m_parser = p;
540*90b80121SDavid van Moolenbroek 	om->m_nextparser = p->p_nextparser;
541*90b80121SDavid van Moolenbroek 	return 0;
542*90b80121SDavid van Moolenbroek }
543*90b80121SDavid van Moolenbroek 
544*90b80121SDavid van Moolenbroek static void
match_cleanup(struct match * dst)545*90b80121SDavid van Moolenbroek match_cleanup(struct match *dst)
546*90b80121SDavid van Moolenbroek {
547*90b80121SDavid van Moolenbroek 	if (dst->m_env != NULL)
548*90b80121SDavid van Moolenbroek 		prop_object_release((prop_object_t)dst->m_env);
549*90b80121SDavid van Moolenbroek 	memset(dst, 0, sizeof(*dst));
550*90b80121SDavid van Moolenbroek }
551*90b80121SDavid van Moolenbroek 
552*90b80121SDavid van Moolenbroek static void
match_copy(struct match * dst,const struct match * src)553*90b80121SDavid van Moolenbroek match_copy(struct match *dst, const struct match *src)
554*90b80121SDavid van Moolenbroek {
555*90b80121SDavid van Moolenbroek 	match_cleanup(dst);
556*90b80121SDavid van Moolenbroek 
557*90b80121SDavid van Moolenbroek 	prop_object_retain((prop_object_t)src->m_env);
558*90b80121SDavid van Moolenbroek 	*dst = *src;
559*90b80121SDavid van Moolenbroek }
560*90b80121SDavid van Moolenbroek 
561*90b80121SDavid van Moolenbroek static int
pbranch_match(const struct parser * p,const struct match * im,struct match * om,int argidx,const char * arg)562*90b80121SDavid van Moolenbroek pbranch_match(const struct parser *p, const struct match *im,
563*90b80121SDavid van Moolenbroek     struct match *om, int argidx, const char *arg)
564*90b80121SDavid van Moolenbroek {
565*90b80121SDavid van Moolenbroek 	const struct parser *nextp;
566*90b80121SDavid van Moolenbroek 	struct branch *b;
567*90b80121SDavid van Moolenbroek 	const struct pbranch *pb = (const struct pbranch *)p;
568*90b80121SDavid van Moolenbroek 	struct match tmpm;
569*90b80121SDavid van Moolenbroek 	int nforbid = 0, nmatch = 0, rc;
570*90b80121SDavid van Moolenbroek 	parser_match_t matchfunc;
571*90b80121SDavid van Moolenbroek 
572*90b80121SDavid van Moolenbroek 	memset(&tmpm, 0, sizeof(tmpm));
573*90b80121SDavid van Moolenbroek 
574*90b80121SDavid van Moolenbroek 	SIMPLEQ_FOREACH(b, &pb->pb_branches, b_next) {
575*90b80121SDavid van Moolenbroek 		nextp = b->b_nextparser;
576*90b80121SDavid van Moolenbroek 		dbg_warnx("%s: b->b_nextparser %p [%s]", __func__,
577*90b80121SDavid van Moolenbroek 		    nextp, nextp ? nextp->p_name : "(null)");
578*90b80121SDavid van Moolenbroek 		if (nextp == NULL) {
579*90b80121SDavid van Moolenbroek 			if (arg == NULL) {
580*90b80121SDavid van Moolenbroek 				nmatch++;
581*90b80121SDavid van Moolenbroek 				match_setenv(im, om, NULL, NULL);
582*90b80121SDavid van Moolenbroek 				om->m_nextparser = NULL;
583*90b80121SDavid van Moolenbroek 				om->m_parser = p;
584*90b80121SDavid van Moolenbroek 				om->m_argidx = argidx;
585*90b80121SDavid van Moolenbroek 			}
586*90b80121SDavid van Moolenbroek 			continue;
587*90b80121SDavid van Moolenbroek 		}
588*90b80121SDavid van Moolenbroek 		matchfunc = nextp->p_methods->pm_match;
589*90b80121SDavid van Moolenbroek 		rc = (*matchfunc)(nextp, im, &tmpm, argidx, arg);
590*90b80121SDavid van Moolenbroek 		if (rc == 0) {
591*90b80121SDavid van Moolenbroek 			match_copy(om, &tmpm);
592*90b80121SDavid van Moolenbroek 			match_cleanup(&tmpm);
593*90b80121SDavid van Moolenbroek 			nmatch++;
594*90b80121SDavid van Moolenbroek 			dbg_warnx("%s: branch %s ok", __func__, nextp->p_name);
595*90b80121SDavid van Moolenbroek 			if (pb->pb_match_first)
596*90b80121SDavid van Moolenbroek 				break;
597*90b80121SDavid van Moolenbroek 		} else if (rc == 1) {
598*90b80121SDavid van Moolenbroek 			nforbid++;
599*90b80121SDavid van Moolenbroek 			if (pb->pb_match_first)
600*90b80121SDavid van Moolenbroek 				break;
601*90b80121SDavid van Moolenbroek 		} else {
602*90b80121SDavid van Moolenbroek 			dbg_warnx("%s: fail branch %s", __func__,
603*90b80121SDavid van Moolenbroek 			    nextp->p_name);
604*90b80121SDavid van Moolenbroek 		}
605*90b80121SDavid van Moolenbroek 	}
606*90b80121SDavid van Moolenbroek 	switch (nmatch) {
607*90b80121SDavid van Moolenbroek 	case 0:
608*90b80121SDavid van Moolenbroek 		errno = ENOENT;
609*90b80121SDavid van Moolenbroek 		return (nforbid == 0) ? -1 : 1;
610*90b80121SDavid van Moolenbroek 	case 1:
611*90b80121SDavid van Moolenbroek 		dbg_warnx("%s: branch ok", __func__);
612*90b80121SDavid van Moolenbroek 		return 0;
613*90b80121SDavid van Moolenbroek 	default:
614*90b80121SDavid van Moolenbroek 		match_cleanup(om);
615*90b80121SDavid van Moolenbroek 		errno = EMLINK;
616*90b80121SDavid van Moolenbroek 		return -1;
617*90b80121SDavid van Moolenbroek 	}
618*90b80121SDavid van Moolenbroek }
619*90b80121SDavid van Moolenbroek 
620*90b80121SDavid van Moolenbroek static int
pkw_match(const struct parser * p,const struct match * im,struct match * om,int argidx,const char * arg)621*90b80121SDavid van Moolenbroek pkw_match(const struct parser *p, const struct match *im,
622*90b80121SDavid van Moolenbroek     struct match *om, int argidx, const char *arg)
623*90b80121SDavid van Moolenbroek {
624*90b80121SDavid van Moolenbroek 	prop_object_t o = NULL;
625*90b80121SDavid van Moolenbroek 	struct kwinst *k;
626*90b80121SDavid van Moolenbroek 	union kwval *u = NULL;
627*90b80121SDavid van Moolenbroek 	const struct pkw *pk = (const struct pkw *)p;
628*90b80121SDavid van Moolenbroek 
629*90b80121SDavid van Moolenbroek 	if (arg == NULL) {
630*90b80121SDavid van Moolenbroek 		errno = EINVAL;
631*90b80121SDavid van Moolenbroek 		return -1;
632*90b80121SDavid van Moolenbroek 	}
633*90b80121SDavid van Moolenbroek 
634*90b80121SDavid van Moolenbroek 	SIMPLEQ_FOREACH(k, &pk->pk_keywords, k_next) {
635*90b80121SDavid van Moolenbroek 		if (k->k_act != NULL &&
636*90b80121SDavid van Moolenbroek 		    prop_dictionary_get(im->m_env, k->k_act) == NULL)
637*90b80121SDavid van Moolenbroek 			continue;
638*90b80121SDavid van Moolenbroek 
639*90b80121SDavid van Moolenbroek 		if (k->k_neg && arg[0] == '-' &&
640*90b80121SDavid van Moolenbroek 		    strcmp(k->k_word, arg + 1) == 0)
641*90b80121SDavid van Moolenbroek 			u = &k->k_negu;
642*90b80121SDavid van Moolenbroek 		else if (strcmp(k->k_word, arg) == 0)
643*90b80121SDavid van Moolenbroek 			u = &k->k_u;
644*90b80121SDavid van Moolenbroek 		else
645*90b80121SDavid van Moolenbroek 			continue;
646*90b80121SDavid van Moolenbroek 
647*90b80121SDavid van Moolenbroek 		if (k->k_altdeact != NULL &&
648*90b80121SDavid van Moolenbroek 		    prop_dictionary_get(im->m_env, k->k_altdeact) != NULL)
649*90b80121SDavid van Moolenbroek 			return 1;
650*90b80121SDavid van Moolenbroek 
651*90b80121SDavid van Moolenbroek 		if (k->k_deact != NULL &&
652*90b80121SDavid van Moolenbroek 		    prop_dictionary_get(im->m_env, k->k_deact) != NULL)
653*90b80121SDavid van Moolenbroek 			return 1;
654*90b80121SDavid van Moolenbroek 		break;
655*90b80121SDavid van Moolenbroek 	}
656*90b80121SDavid van Moolenbroek 	if (k == NULL) {
657*90b80121SDavid van Moolenbroek 		errno = ENOENT;
658*90b80121SDavid van Moolenbroek 		return -1;
659*90b80121SDavid van Moolenbroek 	}
660*90b80121SDavid van Moolenbroek 	switch (k->k_type) {
661*90b80121SDavid van Moolenbroek 	case KW_T_NONE:
662*90b80121SDavid van Moolenbroek 		break;
663*90b80121SDavid van Moolenbroek 	case KW_T_BOOL:
664*90b80121SDavid van Moolenbroek 		o = (prop_object_t)prop_bool_create(u->u_bool);
665*90b80121SDavid van Moolenbroek 		if (o == NULL)
666*90b80121SDavid van Moolenbroek 			goto err;
667*90b80121SDavid van Moolenbroek 		break;
668*90b80121SDavid van Moolenbroek 	case KW_T_INT:
669*90b80121SDavid van Moolenbroek 		o = (prop_object_t)prop_number_create_integer(u->u_sint);
670*90b80121SDavid van Moolenbroek 		if (o == NULL)
671*90b80121SDavid van Moolenbroek 			goto err;
672*90b80121SDavid van Moolenbroek 		break;
673*90b80121SDavid van Moolenbroek 	case KW_T_UINT:
674*90b80121SDavid van Moolenbroek 		o = (prop_object_t)prop_number_create_unsigned_integer(
675*90b80121SDavid van Moolenbroek 		    u->u_uint);
676*90b80121SDavid van Moolenbroek 		if (o == NULL)
677*90b80121SDavid van Moolenbroek 			goto err;
678*90b80121SDavid van Moolenbroek 		break;
679*90b80121SDavid van Moolenbroek 	case KW_T_OBJ:
680*90b80121SDavid van Moolenbroek 		o = u->u_obj;
681*90b80121SDavid van Moolenbroek 		break;
682*90b80121SDavid van Moolenbroek 	case KW_T_STR:
683*90b80121SDavid van Moolenbroek 		o = (prop_object_t)prop_string_create_cstring_nocopy(u->u_str);
684*90b80121SDavid van Moolenbroek 		if (o == NULL)
685*90b80121SDavid van Moolenbroek 			goto err;
686*90b80121SDavid van Moolenbroek 		break;
687*90b80121SDavid van Moolenbroek 	default:
688*90b80121SDavid van Moolenbroek 		errx(EXIT_FAILURE, "unknown keyword type %d", k->k_type);
689*90b80121SDavid van Moolenbroek 	}
690*90b80121SDavid van Moolenbroek 
691*90b80121SDavid van Moolenbroek 	if (match_setenv(im, om, (o == NULL) ? NULL : k->k_key, o) == -1)
692*90b80121SDavid van Moolenbroek 		return -1;
693*90b80121SDavid van Moolenbroek 
694*90b80121SDavid van Moolenbroek 	om->m_argidx = argidx;
695*90b80121SDavid van Moolenbroek 	om->m_parser = p;
696*90b80121SDavid van Moolenbroek 	om->m_nextparser = k->k_nextparser;
697*90b80121SDavid van Moolenbroek 	om->m_exec = k->k_exec;
698*90b80121SDavid van Moolenbroek 	return 0;
699*90b80121SDavid van Moolenbroek err:
700*90b80121SDavid van Moolenbroek 	errno = ENOMEM;
701*90b80121SDavid van Moolenbroek 	return -1;
702*90b80121SDavid van Moolenbroek }
703*90b80121SDavid van Moolenbroek 
704*90b80121SDavid van Moolenbroek struct paddr *
paddr_create(const char * name,parser_exec_t pexec,const char * addrkey,const char * maskkey,struct parser * next)705*90b80121SDavid van Moolenbroek paddr_create(const char *name, parser_exec_t pexec, const char *addrkey,
706*90b80121SDavid van Moolenbroek     const char *maskkey, struct parser *next)
707*90b80121SDavid van Moolenbroek {
708*90b80121SDavid van Moolenbroek 	struct paddr *pa;
709*90b80121SDavid van Moolenbroek 
710*90b80121SDavid van Moolenbroek 	if ((pa = calloc(sizeof(*pa), 1)) == NULL)
711*90b80121SDavid van Moolenbroek 		return NULL;
712*90b80121SDavid van Moolenbroek 
713*90b80121SDavid van Moolenbroek 	pa->pa_parser.p_methods = &paddr_methods;
714*90b80121SDavid van Moolenbroek 	pa->pa_parser.p_exec = pexec;
715*90b80121SDavid van Moolenbroek 	pa->pa_parser.p_name = name;
716*90b80121SDavid van Moolenbroek 	pa->pa_parser.p_nextparser = next;
717*90b80121SDavid van Moolenbroek 
718*90b80121SDavid van Moolenbroek 	pa->pa_addrkey = addrkey;
719*90b80121SDavid van Moolenbroek 	pa->pa_maskkey = maskkey;
720*90b80121SDavid van Moolenbroek 
721*90b80121SDavid van Moolenbroek 	return pa;
722*90b80121SDavid van Moolenbroek }
723*90b80121SDavid van Moolenbroek 
724*90b80121SDavid van Moolenbroek struct piface *
piface_create(const char * name,parser_exec_t pexec,const char * defkey,struct parser * defnext)725*90b80121SDavid van Moolenbroek piface_create(const char *name, parser_exec_t pexec, const char *defkey,
726*90b80121SDavid van Moolenbroek     struct parser *defnext)
727*90b80121SDavid van Moolenbroek {
728*90b80121SDavid van Moolenbroek 	struct piface *pif;
729*90b80121SDavid van Moolenbroek 
730*90b80121SDavid van Moolenbroek 	if ((pif = calloc(sizeof(*pif), 1)) == NULL)
731*90b80121SDavid van Moolenbroek 		return NULL;
732*90b80121SDavid van Moolenbroek 
733*90b80121SDavid van Moolenbroek 	pif->pif_parser.p_methods = &piface_methods;
734*90b80121SDavid van Moolenbroek 	pif->pif_parser.p_exec = pexec;
735*90b80121SDavid van Moolenbroek 	pif->pif_parser.p_name = name;
736*90b80121SDavid van Moolenbroek 	pif->pif_parser.p_nextparser = defnext;
737*90b80121SDavid van Moolenbroek 
738*90b80121SDavid van Moolenbroek 	pif->pif_key = defkey;
739*90b80121SDavid van Moolenbroek 
740*90b80121SDavid van Moolenbroek 	return pif;
741*90b80121SDavid van Moolenbroek }
742*90b80121SDavid van Moolenbroek 
743*90b80121SDavid van Moolenbroek int
pbranch_addbranch(struct pbranch * pb,struct parser * p)744*90b80121SDavid van Moolenbroek pbranch_addbranch(struct pbranch *pb, struct parser *p)
745*90b80121SDavid van Moolenbroek {
746*90b80121SDavid van Moolenbroek 	struct branch *b;
747*90b80121SDavid van Moolenbroek 
748*90b80121SDavid van Moolenbroek 	if ((b = malloc(sizeof(*b))) == NULL)
749*90b80121SDavid van Moolenbroek 		return -1;
750*90b80121SDavid van Moolenbroek 	b->b_nextparser = p;
751*90b80121SDavid van Moolenbroek 	SIMPLEQ_INSERT_HEAD(&pb->pb_branches, b, b_next);
752*90b80121SDavid van Moolenbroek 	pb->pb_parser.p_initialized = false;
753*90b80121SDavid van Moolenbroek 	return parser_init(&pb->pb_parser);
754*90b80121SDavid van Moolenbroek }
755*90b80121SDavid van Moolenbroek 
756*90b80121SDavid van Moolenbroek int
pbranch_setbranches(struct pbranch * pb,const struct branch * brs,size_t nbr)757*90b80121SDavid van Moolenbroek pbranch_setbranches(struct pbranch *pb, const struct branch *brs, size_t nbr)
758*90b80121SDavid van Moolenbroek {
759*90b80121SDavid van Moolenbroek 	struct branch *b;
760*90b80121SDavid van Moolenbroek 	size_t i;
761*90b80121SDavid van Moolenbroek 
762*90b80121SDavid van Moolenbroek 	dbg_warnx("%s: nbr %zu", __func__, nbr);
763*90b80121SDavid van Moolenbroek 
764*90b80121SDavid van Moolenbroek 	while ((b = SIMPLEQ_FIRST(&pb->pb_branches)) != NULL) {
765*90b80121SDavid van Moolenbroek 		SIMPLEQ_REMOVE_HEAD(&pb->pb_branches, b_next);
766*90b80121SDavid van Moolenbroek 		free(b);
767*90b80121SDavid van Moolenbroek 	}
768*90b80121SDavid van Moolenbroek 
769*90b80121SDavid van Moolenbroek 	for (i = 0; i < nbr; i++) {
770*90b80121SDavid van Moolenbroek 		if ((b = malloc(sizeof(*b))) == NULL)
771*90b80121SDavid van Moolenbroek 			goto err;
772*90b80121SDavid van Moolenbroek 		*b = brs[i];
773*90b80121SDavid van Moolenbroek 		dbg_warnx("%s: b->b_nextparser %p [%s]", __func__,
774*90b80121SDavid van Moolenbroek 		    b->b_nextparser, b->b_nextparser ? b->b_nextparser->p_name
775*90b80121SDavid van Moolenbroek 		    : "(null)");
776*90b80121SDavid van Moolenbroek 		SIMPLEQ_INSERT_TAIL(&pb->pb_branches, b, b_next);
777*90b80121SDavid van Moolenbroek 	}
778*90b80121SDavid van Moolenbroek 
779*90b80121SDavid van Moolenbroek 	return 0;
780*90b80121SDavid van Moolenbroek err:
781*90b80121SDavid van Moolenbroek 	while ((b = SIMPLEQ_FIRST(&pb->pb_branches)) != NULL) {
782*90b80121SDavid van Moolenbroek 		SIMPLEQ_REMOVE_HEAD(&pb->pb_branches, b_next);
783*90b80121SDavid van Moolenbroek 		free(b);
784*90b80121SDavid van Moolenbroek 	}
785*90b80121SDavid van Moolenbroek 	return -1;
786*90b80121SDavid van Moolenbroek }
787*90b80121SDavid van Moolenbroek 
788*90b80121SDavid van Moolenbroek static int
pbranch_init(struct parser * p)789*90b80121SDavid van Moolenbroek pbranch_init(struct parser *p)
790*90b80121SDavid van Moolenbroek {
791*90b80121SDavid van Moolenbroek 	struct branch *b;
792*90b80121SDavid van Moolenbroek 	struct pbranch *pb = (struct pbranch *)p;
793*90b80121SDavid van Moolenbroek 	struct parser *np;
794*90b80121SDavid van Moolenbroek 
795*90b80121SDavid van Moolenbroek 	if (pb->pb_nbrinit == 0)
796*90b80121SDavid van Moolenbroek 		;
797*90b80121SDavid van Moolenbroek 	else if (pbranch_setbranches(pb, pb->pb_brinit, pb->pb_nbrinit) == -1)
798*90b80121SDavid van Moolenbroek 		return -1;
799*90b80121SDavid van Moolenbroek 
800*90b80121SDavid van Moolenbroek 	pb->pb_nbrinit = 0;
801*90b80121SDavid van Moolenbroek 
802*90b80121SDavid van Moolenbroek 	SIMPLEQ_FOREACH(b, &pb->pb_branches, b_next) {
803*90b80121SDavid van Moolenbroek 		np = b->b_nextparser;
804*90b80121SDavid van Moolenbroek 		if (np != NULL && parser_init(np) == -1)
805*90b80121SDavid van Moolenbroek 			return -1;
806*90b80121SDavid van Moolenbroek 	}
807*90b80121SDavid van Moolenbroek 	return 0;
808*90b80121SDavid van Moolenbroek }
809*90b80121SDavid van Moolenbroek 
810*90b80121SDavid van Moolenbroek struct pbranch *
pbranch_create(const char * name,const struct branch * brs,size_t nbr,bool match_first)811*90b80121SDavid van Moolenbroek pbranch_create(const char *name, const struct branch *brs, size_t nbr,
812*90b80121SDavid van Moolenbroek     bool match_first)
813*90b80121SDavid van Moolenbroek {
814*90b80121SDavid van Moolenbroek 	struct pbranch *pb;
815*90b80121SDavid van Moolenbroek 
816*90b80121SDavid van Moolenbroek 	dbg_warnx("%s: nbr %zu", __func__, nbr);
817*90b80121SDavid van Moolenbroek 
818*90b80121SDavid van Moolenbroek 	if ((pb = calloc(1, sizeof(*pb))) == NULL)
819*90b80121SDavid van Moolenbroek 		return NULL;
820*90b80121SDavid van Moolenbroek 
821*90b80121SDavid van Moolenbroek 	pb->pb_parser.p_methods = &pbranch_methods;
822*90b80121SDavid van Moolenbroek 	pb->pb_parser.p_name = name;
823*90b80121SDavid van Moolenbroek 
824*90b80121SDavid van Moolenbroek 	SIMPLEQ_INIT(&pb->pb_branches);
825*90b80121SDavid van Moolenbroek 
826*90b80121SDavid van Moolenbroek 	if (pbranch_setbranches(pb, brs, nbr) == -1)
827*90b80121SDavid van Moolenbroek 		goto post_pb_err;
828*90b80121SDavid van Moolenbroek 
829*90b80121SDavid van Moolenbroek 	pb->pb_match_first = match_first;
830*90b80121SDavid van Moolenbroek 	return pb;
831*90b80121SDavid van Moolenbroek post_pb_err:
832*90b80121SDavid van Moolenbroek 	free(pb);
833*90b80121SDavid van Moolenbroek 	return NULL;
834*90b80121SDavid van Moolenbroek }
835*90b80121SDavid van Moolenbroek 
836*90b80121SDavid van Moolenbroek static int
parser_default_init(struct parser * p)837*90b80121SDavid van Moolenbroek parser_default_init(struct parser *p)
838*90b80121SDavid van Moolenbroek {
839*90b80121SDavid van Moolenbroek 	struct parser *np;
840*90b80121SDavid van Moolenbroek 
841*90b80121SDavid van Moolenbroek 	np = p->p_nextparser;
842*90b80121SDavid van Moolenbroek 	if (np != NULL && parser_init(np) == -1)
843*90b80121SDavid van Moolenbroek 		return -1;
844*90b80121SDavid van Moolenbroek 
845*90b80121SDavid van Moolenbroek 	return 0;
846*90b80121SDavid van Moolenbroek }
847*90b80121SDavid van Moolenbroek 
848*90b80121SDavid van Moolenbroek static int
pkw_setwords(struct pkw * pk,parser_exec_t defexec,const char * defkey,const struct kwinst * kws,size_t nkw,struct parser * defnext)849*90b80121SDavid van Moolenbroek pkw_setwords(struct pkw *pk, parser_exec_t defexec, const char *defkey,
850*90b80121SDavid van Moolenbroek     const struct kwinst *kws, size_t nkw, struct parser *defnext)
851*90b80121SDavid van Moolenbroek {
852*90b80121SDavid van Moolenbroek 	struct kwinst *k;
853*90b80121SDavid van Moolenbroek 	size_t i;
854*90b80121SDavid van Moolenbroek 
855*90b80121SDavid van Moolenbroek 	for (i = 0; i < nkw; i++) {
856*90b80121SDavid van Moolenbroek 		if (kws[i].k_word == NULL)
857*90b80121SDavid van Moolenbroek 			continue;
858*90b80121SDavid van Moolenbroek 		if ((k = malloc(sizeof(*k))) == NULL)
859*90b80121SDavid van Moolenbroek 			goto post_pk_err;
860*90b80121SDavid van Moolenbroek 		*k = kws[i];
861*90b80121SDavid van Moolenbroek 		if (k->k_nextparser == NULL)
862*90b80121SDavid van Moolenbroek 			k->k_nextparser = defnext;
863*90b80121SDavid van Moolenbroek 		if (k->k_key == NULL)
864*90b80121SDavid van Moolenbroek 			k->k_key = defkey;
865*90b80121SDavid van Moolenbroek 		if (k->k_exec == NULL)
866*90b80121SDavid van Moolenbroek 			k->k_exec = defexec;
867*90b80121SDavid van Moolenbroek 		SIMPLEQ_INSERT_TAIL(&pk->pk_keywords, k, k_next);
868*90b80121SDavid van Moolenbroek 	}
869*90b80121SDavid van Moolenbroek 	return 0;
870*90b80121SDavid van Moolenbroek 
871*90b80121SDavid van Moolenbroek post_pk_err:
872*90b80121SDavid van Moolenbroek 	while ((k = SIMPLEQ_FIRST(&pk->pk_keywords)) != NULL) {
873*90b80121SDavid van Moolenbroek 		SIMPLEQ_REMOVE_HEAD(&pk->pk_keywords, k_next);
874*90b80121SDavid van Moolenbroek 		free(k);
875*90b80121SDavid van Moolenbroek 	}
876*90b80121SDavid van Moolenbroek 	return -1;
877*90b80121SDavid van Moolenbroek }
878*90b80121SDavid van Moolenbroek 
879*90b80121SDavid van Moolenbroek static int
pkw_init(struct parser * p)880*90b80121SDavid van Moolenbroek pkw_init(struct parser *p)
881*90b80121SDavid van Moolenbroek {
882*90b80121SDavid van Moolenbroek 	struct kwinst *k;
883*90b80121SDavid van Moolenbroek 	struct pkw *pk = (struct pkw *)p;
884*90b80121SDavid van Moolenbroek 	struct parser *np;
885*90b80121SDavid van Moolenbroek 
886*90b80121SDavid van Moolenbroek 	if (pk->pk_nkwinit == 0)
887*90b80121SDavid van Moolenbroek 		;
888*90b80121SDavid van Moolenbroek 	else if (pkw_setwords(pk, pk->pk_execinit, pk->pk_keyinit,
889*90b80121SDavid van Moolenbroek 	    pk->pk_kwinit, pk->pk_nkwinit, pk->pk_nextinit) == -1)
890*90b80121SDavid van Moolenbroek 		return -1;
891*90b80121SDavid van Moolenbroek 
892*90b80121SDavid van Moolenbroek 	pk->pk_nkwinit = 0;
893*90b80121SDavid van Moolenbroek 
894*90b80121SDavid van Moolenbroek 	SIMPLEQ_FOREACH(k, &pk->pk_keywords, k_next) {
895*90b80121SDavid van Moolenbroek 		np = k->k_nextparser;
896*90b80121SDavid van Moolenbroek 		if (np != NULL && parser_init(np) == -1)
897*90b80121SDavid van Moolenbroek 			return -1;
898*90b80121SDavid van Moolenbroek 	}
899*90b80121SDavid van Moolenbroek 	return 0;
900*90b80121SDavid van Moolenbroek }
901*90b80121SDavid van Moolenbroek 
902*90b80121SDavid van Moolenbroek struct pkw *
pkw_create(const char * name,parser_exec_t defexec,const char * defkey,const struct kwinst * kws,size_t nkw,struct parser * defnext)903*90b80121SDavid van Moolenbroek pkw_create(const char *name, parser_exec_t defexec, const char *defkey,
904*90b80121SDavid van Moolenbroek     const struct kwinst *kws, size_t nkw, struct parser *defnext)
905*90b80121SDavid van Moolenbroek {
906*90b80121SDavid van Moolenbroek 	struct pkw *pk;
907*90b80121SDavid van Moolenbroek 
908*90b80121SDavid van Moolenbroek 	if ((pk = calloc(1, sizeof(*pk))) == NULL)
909*90b80121SDavid van Moolenbroek 		return NULL;
910*90b80121SDavid van Moolenbroek 
911*90b80121SDavid van Moolenbroek 	pk->pk_parser.p_methods = &pkw_methods;
912*90b80121SDavid van Moolenbroek 	pk->pk_parser.p_exec = defexec;
913*90b80121SDavid van Moolenbroek 	pk->pk_parser.p_name = name;
914*90b80121SDavid van Moolenbroek 
915*90b80121SDavid van Moolenbroek 	SIMPLEQ_INIT(&pk->pk_keywords);
916*90b80121SDavid van Moolenbroek 
917*90b80121SDavid van Moolenbroek 	if (pkw_setwords(pk, defexec, defkey, kws, nkw, defnext) == -1)
918*90b80121SDavid van Moolenbroek 		goto err;
919*90b80121SDavid van Moolenbroek 
920*90b80121SDavid van Moolenbroek 	return pk;
921*90b80121SDavid van Moolenbroek err:
922*90b80121SDavid van Moolenbroek 	free(pk);
923*90b80121SDavid van Moolenbroek 	return NULL;
924*90b80121SDavid van Moolenbroek }
925*90b80121SDavid van Moolenbroek 
926*90b80121SDavid van Moolenbroek int
parse(int argc,char ** argv,const struct parser * p0,struct match * matches,size_t * nmatch,int * narg)927*90b80121SDavid van Moolenbroek parse(int argc, char **argv, const struct parser *p0, struct match *matches,
928*90b80121SDavid van Moolenbroek     size_t *nmatch, int *narg)
929*90b80121SDavid van Moolenbroek {
930*90b80121SDavid van Moolenbroek 	int i, rc = 0;
931*90b80121SDavid van Moolenbroek 	struct match *lastm = NULL, *m = matches;
932*90b80121SDavid van Moolenbroek 	const struct parser *p = p0;
933*90b80121SDavid van Moolenbroek 
934*90b80121SDavid van Moolenbroek 	for (i = 0; i < argc && p != NULL; i++) {
935*90b80121SDavid van Moolenbroek 		if ((size_t)(m - matches) >= *nmatch) {
936*90b80121SDavid van Moolenbroek 			errno = EFBIG;
937*90b80121SDavid van Moolenbroek 			rc = -1;
938*90b80121SDavid van Moolenbroek 			break;
939*90b80121SDavid van Moolenbroek 		}
940*90b80121SDavid van Moolenbroek 		rc = (*p->p_methods->pm_match)(p, lastm, m, i, argv[i]);
941*90b80121SDavid van Moolenbroek 		if (rc != 0)
942*90b80121SDavid van Moolenbroek 			goto out;
943*90b80121SDavid van Moolenbroek 		p = m->m_nextparser;
944*90b80121SDavid van Moolenbroek 		lastm = m++;
945*90b80121SDavid van Moolenbroek 	}
946*90b80121SDavid van Moolenbroek 	for (; (size_t)(m - matches) < *nmatch && p != NULL; ) {
947*90b80121SDavid van Moolenbroek 		rc = (*p->p_methods->pm_match)(p, lastm, m, i, NULL);
948*90b80121SDavid van Moolenbroek 		if (rc != 0)
949*90b80121SDavid van Moolenbroek 			break;
950*90b80121SDavid van Moolenbroek 		p = m->m_nextparser;
951*90b80121SDavid van Moolenbroek 		lastm = m++;
952*90b80121SDavid van Moolenbroek 	}
953*90b80121SDavid van Moolenbroek out:
954*90b80121SDavid van Moolenbroek 	*nmatch = m - matches;
955*90b80121SDavid van Moolenbroek 	*narg = i;
956*90b80121SDavid van Moolenbroek 	return rc;
957*90b80121SDavid van Moolenbroek }
958*90b80121SDavid van Moolenbroek 
959*90b80121SDavid van Moolenbroek int
matches_exec(const struct match * matches,prop_dictionary_t oenv,size_t nmatch)960*90b80121SDavid van Moolenbroek matches_exec(const struct match *matches, prop_dictionary_t oenv, size_t nmatch)
961*90b80121SDavid van Moolenbroek {
962*90b80121SDavid van Moolenbroek 	size_t i;
963*90b80121SDavid van Moolenbroek 	int rc = 0;
964*90b80121SDavid van Moolenbroek 	const struct match *m;
965*90b80121SDavid van Moolenbroek 	parser_exec_t pexec;
966*90b80121SDavid van Moolenbroek 	prop_dictionary_t d;
967*90b80121SDavid van Moolenbroek 
968*90b80121SDavid van Moolenbroek 	for (i = 0; i < nmatch; i++) {
969*90b80121SDavid van Moolenbroek 		m = &matches[i];
970*90b80121SDavid van Moolenbroek 		dbg_warnx("%s.%d: i %zu", __func__, __LINE__, i);
971*90b80121SDavid van Moolenbroek 		pexec = (m->m_parser->p_exec != NULL)
972*90b80121SDavid van Moolenbroek 		    ? m->m_parser->p_exec : m->m_exec;
973*90b80121SDavid van Moolenbroek 		if (pexec == NULL)
974*90b80121SDavid van Moolenbroek 			continue;
975*90b80121SDavid van Moolenbroek 		dbg_warnx("%s.%d: m->m_parser->p_name %s", __func__, __LINE__,
976*90b80121SDavid van Moolenbroek 		    m->m_parser->p_name);
977*90b80121SDavid van Moolenbroek 		d = prop_dictionary_augment(m->m_env, oenv);
978*90b80121SDavid van Moolenbroek 		rc = (*pexec)(d, oenv);
979*90b80121SDavid van Moolenbroek 		prop_object_release((prop_object_t)d);
980*90b80121SDavid van Moolenbroek 		if (rc == -1)
981*90b80121SDavid van Moolenbroek 			break;
982*90b80121SDavid van Moolenbroek 	}
983*90b80121SDavid van Moolenbroek 	return rc;
984*90b80121SDavid van Moolenbroek }
985*90b80121SDavid van Moolenbroek 
986*90b80121SDavid van Moolenbroek int
parser_init(struct parser * p)987*90b80121SDavid van Moolenbroek parser_init(struct parser *p)
988*90b80121SDavid van Moolenbroek {
989*90b80121SDavid van Moolenbroek 	if (p->p_initialized)
990*90b80121SDavid van Moolenbroek 		return 0;
991*90b80121SDavid van Moolenbroek 	p->p_initialized = true;
992*90b80121SDavid van Moolenbroek 	if (p->p_methods->pm_init == NULL)
993*90b80121SDavid van Moolenbroek 		return 0;
994*90b80121SDavid van Moolenbroek 	return (*p->p_methods->pm_init)(p);
995*90b80121SDavid van Moolenbroek }
996