Deleted Added
full compact
parse.y (204076) parse.y (207371)
1%{
2/*-
3 * Copyright (c) 2009-2010 The FreeBSD Foundation
4 * All rights reserved.
5 *
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
1%{
2/*-
3 * Copyright (c) 2009-2010 The FreeBSD Foundation
4 * All rights reserved.
5 *
6 * This software was developed by Pawel Jakub Dawidek under sponsorship from
7 * the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $FreeBSD: head/sbin/hastd/parse.y 204076 2010-02-18 23:16:19Z pjd $
30 * $FreeBSD: head/sbin/hastd/parse.y 207371 2010-04-29 15:36:32Z pjd $
31 */
32
33#include <sys/param.h> /* MAXHOSTNAMELEN */
34#include <sys/queue.h>
35#include <sys/sysctl.h>
36
37#include <arpa/inet.h>
38
39#include <assert.h>
40#include <err.h>
41#include <stdio.h>
42#include <string.h>
43#include <sysexits.h>
44#include <unistd.h>
45
46#include "hast.h"
47
48extern int depth;
49extern int lineno;
50
51extern FILE *yyin;
52extern char *yytext;
53
54static struct hastd_config lconfig;
55static struct hast_resource *curres;
56static bool mynode;
57
58static char depth0_control[HAST_ADDRSIZE];
59static char depth0_listen[HAST_ADDRSIZE];
60static int depth0_replication;
31 */
32
33#include <sys/param.h> /* MAXHOSTNAMELEN */
34#include <sys/queue.h>
35#include <sys/sysctl.h>
36
37#include <arpa/inet.h>
38
39#include <assert.h>
40#include <err.h>
41#include <stdio.h>
42#include <string.h>
43#include <sysexits.h>
44#include <unistd.h>
45
46#include "hast.h"
47
48extern int depth;
49extern int lineno;
50
51extern FILE *yyin;
52extern char *yytext;
53
54static struct hastd_config lconfig;
55static struct hast_resource *curres;
56static bool mynode;
57
58static char depth0_control[HAST_ADDRSIZE];
59static char depth0_listen[HAST_ADDRSIZE];
60static int depth0_replication;
61static int depth0_timeout;
61
62static char depth1_provname[PATH_MAX];
63static char depth1_localpath[PATH_MAX];
64
65static bool
66isitme(const char *name)
67{
68 char buf[MAXHOSTNAMELEN];
69 char *pos;
70 size_t bufsize;
71
72 /*
73 * First check if the give name matches our full hostname.
74 */
75 if (gethostname(buf, sizeof(buf)) < 0)
76 err(EX_OSERR, "gethostname() failed");
77 if (strcmp(buf, name) == 0)
78 return (true);
79
80 /*
81 * Now check if it matches first part of the host name.
82 */
83 pos = strchr(buf, '.');
84 if (pos != NULL && pos != buf && strncmp(buf, name, pos - buf) == 0)
85 return (true);
86
87 /*
88 * At the end check if name is equal to our host's UUID.
89 */
90 bufsize = sizeof(buf);
91 if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0)
92 err(EX_OSERR, "sysctlbyname(kern.hostuuid) failed");
93 if (strcasecmp(buf, name) == 0)
94 return (true);
95
96 /*
97 * Looks like this isn't about us.
98 */
99 return (false);
100}
101
102void
103yyerror(const char *str)
104{
105
106 fprintf(stderr, "error at line %d near '%s': %s\n",
107 lineno, yytext, str);
108}
109
110struct hastd_config *
111yy_config_parse(const char *config)
112{
113 int ret;
114
115 curres = NULL;
116 mynode = false;
117
62
63static char depth1_provname[PATH_MAX];
64static char depth1_localpath[PATH_MAX];
65
66static bool
67isitme(const char *name)
68{
69 char buf[MAXHOSTNAMELEN];
70 char *pos;
71 size_t bufsize;
72
73 /*
74 * First check if the give name matches our full hostname.
75 */
76 if (gethostname(buf, sizeof(buf)) < 0)
77 err(EX_OSERR, "gethostname() failed");
78 if (strcmp(buf, name) == 0)
79 return (true);
80
81 /*
82 * Now check if it matches first part of the host name.
83 */
84 pos = strchr(buf, '.');
85 if (pos != NULL && pos != buf && strncmp(buf, name, pos - buf) == 0)
86 return (true);
87
88 /*
89 * At the end check if name is equal to our host's UUID.
90 */
91 bufsize = sizeof(buf);
92 if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0)
93 err(EX_OSERR, "sysctlbyname(kern.hostuuid) failed");
94 if (strcasecmp(buf, name) == 0)
95 return (true);
96
97 /*
98 * Looks like this isn't about us.
99 */
100 return (false);
101}
102
103void
104yyerror(const char *str)
105{
106
107 fprintf(stderr, "error at line %d near '%s': %s\n",
108 lineno, yytext, str);
109}
110
111struct hastd_config *
112yy_config_parse(const char *config)
113{
114 int ret;
115
116 curres = NULL;
117 mynode = false;
118
119 depth0_timeout = HAST_TIMEOUT;
118 depth0_replication = HAST_REPLICATION_MEMSYNC;
119 strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control));
120 strlcpy(depth0_listen, HASTD_LISTEN, sizeof(depth0_listen));
121
122 TAILQ_INIT(&lconfig.hc_resources);
123
124 yyin = fopen(config, "r");
125 if (yyin == NULL)
126 err(EX_OSFILE, "cannot open configuration file %s", config);
127 ret = yyparse();
128 fclose(yyin);
129 if (ret != 0) {
130 yy_config_free(&lconfig);
131 exit(EX_CONFIG);
132 }
133
134 /*
135 * Let's see if everything is set up.
136 */
137 if (lconfig.hc_controladdr[0] == '\0') {
138 strlcpy(lconfig.hc_controladdr, depth0_control,
139 sizeof(lconfig.hc_controladdr));
140 }
141 if (lconfig.hc_listenaddr[0] == '\0') {
142 strlcpy(lconfig.hc_listenaddr, depth0_listen,
143 sizeof(lconfig.hc_listenaddr));
144 }
145 TAILQ_FOREACH(curres, &lconfig.hc_resources, hr_next) {
146 assert(curres->hr_provname[0] != '\0');
147 assert(curres->hr_localpath[0] != '\0');
148 assert(curres->hr_remoteaddr[0] != '\0');
149
150 if (curres->hr_replication == -1) {
151 /*
152 * Replication is not set at resource-level.
153 * Use global or default setting.
154 */
155 curres->hr_replication = depth0_replication;
156 }
120 depth0_replication = HAST_REPLICATION_MEMSYNC;
121 strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control));
122 strlcpy(depth0_listen, HASTD_LISTEN, sizeof(depth0_listen));
123
124 TAILQ_INIT(&lconfig.hc_resources);
125
126 yyin = fopen(config, "r");
127 if (yyin == NULL)
128 err(EX_OSFILE, "cannot open configuration file %s", config);
129 ret = yyparse();
130 fclose(yyin);
131 if (ret != 0) {
132 yy_config_free(&lconfig);
133 exit(EX_CONFIG);
134 }
135
136 /*
137 * Let's see if everything is set up.
138 */
139 if (lconfig.hc_controladdr[0] == '\0') {
140 strlcpy(lconfig.hc_controladdr, depth0_control,
141 sizeof(lconfig.hc_controladdr));
142 }
143 if (lconfig.hc_listenaddr[0] == '\0') {
144 strlcpy(lconfig.hc_listenaddr, depth0_listen,
145 sizeof(lconfig.hc_listenaddr));
146 }
147 TAILQ_FOREACH(curres, &lconfig.hc_resources, hr_next) {
148 assert(curres->hr_provname[0] != '\0');
149 assert(curres->hr_localpath[0] != '\0');
150 assert(curres->hr_remoteaddr[0] != '\0');
151
152 if (curres->hr_replication == -1) {
153 /*
154 * Replication is not set at resource-level.
155 * Use global or default setting.
156 */
157 curres->hr_replication = depth0_replication;
158 }
159 if (curres->hr_timeout == -1) {
160 /*
161 * Timeout is not set at resource-level.
162 * Use global or default setting.
163 */
164 curres->hr_timeout = depth0_timeout;
165 }
157 }
158
159 return (&lconfig);
160}
161
162void
163yy_config_free(struct hastd_config *config)
164{
165 struct hast_resource *res;
166
167 while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) {
168 TAILQ_REMOVE(&config->hc_resources, res, hr_next);
169 free(res);
170 }
171}
172%}
173
166 }
167
168 return (&lconfig);
169}
170
171void
172yy_config_free(struct hastd_config *config)
173{
174 struct hast_resource *res;
175
176 while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) {
177 TAILQ_REMOVE(&config->hc_resources, res, hr_next);
178 free(res);
179 }
180}
181%}
182
174%token CONTROL LISTEN PORT REPLICATION EXTENTSIZE RESOURCE NAME LOCAL REMOTE ON
183%token CONTROL LISTEN PORT REPLICATION TIMEOUT EXTENTSIZE RESOURCE NAME LOCAL REMOTE ON
175%token FULLSYNC MEMSYNC ASYNC
176%token NUM STR OB CB
177
178%type <num> replication_type
179
180%union
181{
182 int num;
183 char *str;
184}
185
186%token <num> NUM
187%token <str> STR
188
189%%
190
191statements:
192 |
193 statements statement
194 ;
195
196statement:
197 control_statement
198 |
199 listen_statement
200 |
201 replication_statement
202 |
184%token FULLSYNC MEMSYNC ASYNC
185%token NUM STR OB CB
186
187%type <num> replication_type
188
189%union
190{
191 int num;
192 char *str;
193}
194
195%token <num> NUM
196%token <str> STR
197
198%%
199
200statements:
201 |
202 statements statement
203 ;
204
205statement:
206 control_statement
207 |
208 listen_statement
209 |
210 replication_statement
211 |
212 timeout_statement
213 |
203 node_statement
204 |
205 resource_statement
206 ;
207
208control_statement: CONTROL STR
209 {
210 switch (depth) {
211 case 0:
212 if (strlcpy(depth0_control, $2,
213 sizeof(depth0_control)) >=
214 sizeof(depth0_control)) {
215 errx(EX_CONFIG, "control argument too long");
216 }
217 break;
218 case 1:
219 if (mynode) {
220 if (strlcpy(lconfig.hc_controladdr, $2,
221 sizeof(lconfig.hc_controladdr)) >=
222 sizeof(lconfig.hc_controladdr)) {
223 errx(EX_CONFIG,
224 "control argument too long");
225 }
226 }
227 break;
228 default:
229 assert(!"control at wrong depth level");
230 }
231 }
232 ;
233
234listen_statement: LISTEN STR
235 {
236 switch (depth) {
237 case 0:
238 if (strlcpy(depth0_listen, $2,
239 sizeof(depth0_listen)) >=
240 sizeof(depth0_listen)) {
241 errx(EX_CONFIG, "listen argument too long");
242 }
243 break;
244 case 1:
245 if (mynode) {
246 if (strlcpy(lconfig.hc_listenaddr, $2,
247 sizeof(lconfig.hc_listenaddr)) >=
248 sizeof(lconfig.hc_listenaddr)) {
249 errx(EX_CONFIG,
250 "listen argument too long");
251 }
252 }
253 break;
254 default:
255 assert(!"listen at wrong depth level");
256 }
257 }
258 ;
259
260replication_statement: REPLICATION replication_type
261 {
262 switch (depth) {
263 case 0:
264 depth0_replication = $2;
265 break;
266 case 1:
267 if (curres != NULL)
268 curres->hr_replication = $2;
269 break;
270 default:
271 assert(!"replication at wrong depth level");
272 }
273 }
274 ;
275
276replication_type:
277 FULLSYNC { $$ = HAST_REPLICATION_FULLSYNC; }
278 |
279 MEMSYNC { $$ = HAST_REPLICATION_MEMSYNC; }
280 |
281 ASYNC { $$ = HAST_REPLICATION_ASYNC; }
282 ;
283
214 node_statement
215 |
216 resource_statement
217 ;
218
219control_statement: CONTROL STR
220 {
221 switch (depth) {
222 case 0:
223 if (strlcpy(depth0_control, $2,
224 sizeof(depth0_control)) >=
225 sizeof(depth0_control)) {
226 errx(EX_CONFIG, "control argument too long");
227 }
228 break;
229 case 1:
230 if (mynode) {
231 if (strlcpy(lconfig.hc_controladdr, $2,
232 sizeof(lconfig.hc_controladdr)) >=
233 sizeof(lconfig.hc_controladdr)) {
234 errx(EX_CONFIG,
235 "control argument too long");
236 }
237 }
238 break;
239 default:
240 assert(!"control at wrong depth level");
241 }
242 }
243 ;
244
245listen_statement: LISTEN STR
246 {
247 switch (depth) {
248 case 0:
249 if (strlcpy(depth0_listen, $2,
250 sizeof(depth0_listen)) >=
251 sizeof(depth0_listen)) {
252 errx(EX_CONFIG, "listen argument too long");
253 }
254 break;
255 case 1:
256 if (mynode) {
257 if (strlcpy(lconfig.hc_listenaddr, $2,
258 sizeof(lconfig.hc_listenaddr)) >=
259 sizeof(lconfig.hc_listenaddr)) {
260 errx(EX_CONFIG,
261 "listen argument too long");
262 }
263 }
264 break;
265 default:
266 assert(!"listen at wrong depth level");
267 }
268 }
269 ;
270
271replication_statement: REPLICATION replication_type
272 {
273 switch (depth) {
274 case 0:
275 depth0_replication = $2;
276 break;
277 case 1:
278 if (curres != NULL)
279 curres->hr_replication = $2;
280 break;
281 default:
282 assert(!"replication at wrong depth level");
283 }
284 }
285 ;
286
287replication_type:
288 FULLSYNC { $$ = HAST_REPLICATION_FULLSYNC; }
289 |
290 MEMSYNC { $$ = HAST_REPLICATION_MEMSYNC; }
291 |
292 ASYNC { $$ = HAST_REPLICATION_ASYNC; }
293 ;
294
295timeout_statement: TIMEOUT NUM
296 {
297 switch (depth) {
298 case 0:
299 depth0_timeout = $2;
300 break;
301 case 1:
302 if (curres != NULL)
303 curres->hr_timeout = $2;
304 break;
305 default:
306 assert(!"timeout at wrong depth level");
307 }
308 }
309 ;
310
284node_statement: ON node_start OB node_entries CB
285 {
286 mynode = false;
287 }
288 ;
289
290node_start: STR
291 {
292 if (isitme($1))
293 mynode = true;
294 }
295 ;
296
297node_entries:
298 |
299 node_entries node_entry
300 ;
301
302node_entry:
303 control_statement
304 |
305 listen_statement
306 ;
307
308resource_statement: RESOURCE resource_start OB resource_entries CB
309 {
310 if (curres != NULL) {
311 /*
312 * Let's see there are some resource-level settings
313 * that we can use for node-level settings.
314 */
315 if (curres->hr_provname[0] == '\0' &&
316 depth1_provname[0] != '\0') {
317 /*
318 * Provider name is not set at node-level,
319 * but is set at resource-level, use it.
320 */
321 strlcpy(curres->hr_provname, depth1_provname,
322 sizeof(curres->hr_provname));
323 }
324 if (curres->hr_localpath[0] == '\0' &&
325 depth1_localpath[0] != '\0') {
326 /*
327 * Path to local provider is not set at
328 * node-level, but is set at resource-level,
329 * use it.
330 */
331 strlcpy(curres->hr_localpath, depth1_localpath,
332 sizeof(curres->hr_localpath));
333 }
334
335 /*
336 * If provider name is not given, use resource name
337 * as provider name.
338 */
339 if (curres->hr_provname[0] == '\0') {
340 strlcpy(curres->hr_provname, curres->hr_name,
341 sizeof(curres->hr_provname));
342 }
343
344 /*
345 * Remote address has to be configured at this point.
346 */
347 if (curres->hr_remoteaddr[0] == '\0') {
348 errx(EX_CONFIG,
349 "remote address not configured for resource %s",
350 curres->hr_name);
351 }
352 /*
353 * Path to local provider has to be configured at this
354 * point.
355 */
356 if (curres->hr_localpath[0] == '\0') {
357 errx(EX_CONFIG,
358 "path local component not configured for resource %s",
359 curres->hr_name);
360 }
361
362 /* Put it onto resource list. */
363 TAILQ_INSERT_TAIL(&lconfig.hc_resources, curres, hr_next);
364 curres = NULL;
365 }
366 }
367 ;
368
369resource_start: STR
370 {
371 /*
372 * Clear those, so we can tell if they were set at
373 * resource-level or not.
374 */
375 depth1_provname[0] = '\0';
376 depth1_localpath[0] = '\0';
377
378 curres = calloc(1, sizeof(*curres));
379 if (curres == NULL) {
380 errx(EX_TEMPFAIL,
381 "cannot allocate memory for resource");
382 }
383 if (strlcpy(curres->hr_name, $1,
384 sizeof(curres->hr_name)) >=
385 sizeof(curres->hr_name)) {
386 errx(EX_CONFIG,
387 "resource name (%s) too long", $1);
388 }
389 curres->hr_role = HAST_ROLE_INIT;
390 curres->hr_previous_role = HAST_ROLE_INIT;
391 curres->hr_replication = -1;
311node_statement: ON node_start OB node_entries CB
312 {
313 mynode = false;
314 }
315 ;
316
317node_start: STR
318 {
319 if (isitme($1))
320 mynode = true;
321 }
322 ;
323
324node_entries:
325 |
326 node_entries node_entry
327 ;
328
329node_entry:
330 control_statement
331 |
332 listen_statement
333 ;
334
335resource_statement: RESOURCE resource_start OB resource_entries CB
336 {
337 if (curres != NULL) {
338 /*
339 * Let's see there are some resource-level settings
340 * that we can use for node-level settings.
341 */
342 if (curres->hr_provname[0] == '\0' &&
343 depth1_provname[0] != '\0') {
344 /*
345 * Provider name is not set at node-level,
346 * but is set at resource-level, use it.
347 */
348 strlcpy(curres->hr_provname, depth1_provname,
349 sizeof(curres->hr_provname));
350 }
351 if (curres->hr_localpath[0] == '\0' &&
352 depth1_localpath[0] != '\0') {
353 /*
354 * Path to local provider is not set at
355 * node-level, but is set at resource-level,
356 * use it.
357 */
358 strlcpy(curres->hr_localpath, depth1_localpath,
359 sizeof(curres->hr_localpath));
360 }
361
362 /*
363 * If provider name is not given, use resource name
364 * as provider name.
365 */
366 if (curres->hr_provname[0] == '\0') {
367 strlcpy(curres->hr_provname, curres->hr_name,
368 sizeof(curres->hr_provname));
369 }
370
371 /*
372 * Remote address has to be configured at this point.
373 */
374 if (curres->hr_remoteaddr[0] == '\0') {
375 errx(EX_CONFIG,
376 "remote address not configured for resource %s",
377 curres->hr_name);
378 }
379 /*
380 * Path to local provider has to be configured at this
381 * point.
382 */
383 if (curres->hr_localpath[0] == '\0') {
384 errx(EX_CONFIG,
385 "path local component not configured for resource %s",
386 curres->hr_name);
387 }
388
389 /* Put it onto resource list. */
390 TAILQ_INSERT_TAIL(&lconfig.hc_resources, curres, hr_next);
391 curres = NULL;
392 }
393 }
394 ;
395
396resource_start: STR
397 {
398 /*
399 * Clear those, so we can tell if they were set at
400 * resource-level or not.
401 */
402 depth1_provname[0] = '\0';
403 depth1_localpath[0] = '\0';
404
405 curres = calloc(1, sizeof(*curres));
406 if (curres == NULL) {
407 errx(EX_TEMPFAIL,
408 "cannot allocate memory for resource");
409 }
410 if (strlcpy(curres->hr_name, $1,
411 sizeof(curres->hr_name)) >=
412 sizeof(curres->hr_name)) {
413 errx(EX_CONFIG,
414 "resource name (%s) too long", $1);
415 }
416 curres->hr_role = HAST_ROLE_INIT;
417 curres->hr_previous_role = HAST_ROLE_INIT;
418 curres->hr_replication = -1;
419 curres->hr_timeout = -1;
392 curres->hr_provname[0] = '\0';
393 curres->hr_localpath[0] = '\0';
394 curres->hr_localfd = -1;
395 curres->hr_remoteaddr[0] = '\0';
396 curres->hr_ggateunit = -1;
397 }
398 ;
399
400resource_entries:
401 |
402 resource_entries resource_entry
403 ;
404
405resource_entry:
406 replication_statement
407 |
420 curres->hr_provname[0] = '\0';
421 curres->hr_localpath[0] = '\0';
422 curres->hr_localfd = -1;
423 curres->hr_remoteaddr[0] = '\0';
424 curres->hr_ggateunit = -1;
425 }
426 ;
427
428resource_entries:
429 |
430 resource_entries resource_entry
431 ;
432
433resource_entry:
434 replication_statement
435 |
436 timeout_statement
437 |
408 name_statement
409 |
410 local_statement
411 |
412 resource_node_statement
413 ;
414
415name_statement: NAME STR
416 {
417 switch (depth) {
418 case 1:
419 if (strlcpy(depth1_provname, $2,
420 sizeof(depth1_provname)) >=
421 sizeof(depth1_provname)) {
422 errx(EX_CONFIG, "name argument too long");
423 }
424 break;
425 case 2:
426 if (mynode) {
427 assert(curres != NULL);
428 if (strlcpy(curres->hr_provname, $2,
429 sizeof(curres->hr_provname)) >=
430 sizeof(curres->hr_provname)) {
431 errx(EX_CONFIG,
432 "name argument too long");
433 }
434 }
435 break;
436 default:
437 assert(!"name at wrong depth level");
438 }
439 }
440 ;
441
442local_statement: LOCAL STR
443 {
444 switch (depth) {
445 case 1:
446 if (strlcpy(depth1_localpath, $2,
447 sizeof(depth1_localpath)) >=
448 sizeof(depth1_localpath)) {
449 errx(EX_CONFIG, "local argument too long");
450 }
451 break;
452 case 2:
453 if (mynode) {
454 assert(curres != NULL);
455 if (strlcpy(curres->hr_localpath, $2,
456 sizeof(curres->hr_localpath)) >=
457 sizeof(curres->hr_localpath)) {
458 errx(EX_CONFIG,
459 "local argument too long");
460 }
461 }
462 break;
463 default:
464 assert(!"local at wrong depth level");
465 }
466 }
467 ;
468
469resource_node_statement:ON resource_node_start OB resource_node_entries CB
470 {
471 mynode = false;
472 }
473 ;
474
475resource_node_start: STR
476 {
477 if (curres != NULL && isitme($1))
478 mynode = true;
479 }
480 ;
481
482resource_node_entries:
483 |
484 resource_node_entries resource_node_entry
485 ;
486
487resource_node_entry:
488 name_statement
489 |
490 local_statement
491 |
492 remote_statement
493 ;
494
495remote_statement: REMOTE STR
496 {
497 assert(depth == 2);
498 if (mynode) {
499 assert(curres != NULL);
500 if (strlcpy(curres->hr_remoteaddr, $2,
501 sizeof(curres->hr_remoteaddr)) >=
502 sizeof(curres->hr_remoteaddr)) {
503 errx(EX_CONFIG, "remote argument too long");
504 }
505 }
506 }
507 ;
438 name_statement
439 |
440 local_statement
441 |
442 resource_node_statement
443 ;
444
445name_statement: NAME STR
446 {
447 switch (depth) {
448 case 1:
449 if (strlcpy(depth1_provname, $2,
450 sizeof(depth1_provname)) >=
451 sizeof(depth1_provname)) {
452 errx(EX_CONFIG, "name argument too long");
453 }
454 break;
455 case 2:
456 if (mynode) {
457 assert(curres != NULL);
458 if (strlcpy(curres->hr_provname, $2,
459 sizeof(curres->hr_provname)) >=
460 sizeof(curres->hr_provname)) {
461 errx(EX_CONFIG,
462 "name argument too long");
463 }
464 }
465 break;
466 default:
467 assert(!"name at wrong depth level");
468 }
469 }
470 ;
471
472local_statement: LOCAL STR
473 {
474 switch (depth) {
475 case 1:
476 if (strlcpy(depth1_localpath, $2,
477 sizeof(depth1_localpath)) >=
478 sizeof(depth1_localpath)) {
479 errx(EX_CONFIG, "local argument too long");
480 }
481 break;
482 case 2:
483 if (mynode) {
484 assert(curres != NULL);
485 if (strlcpy(curres->hr_localpath, $2,
486 sizeof(curres->hr_localpath)) >=
487 sizeof(curres->hr_localpath)) {
488 errx(EX_CONFIG,
489 "local argument too long");
490 }
491 }
492 break;
493 default:
494 assert(!"local at wrong depth level");
495 }
496 }
497 ;
498
499resource_node_statement:ON resource_node_start OB resource_node_entries CB
500 {
501 mynode = false;
502 }
503 ;
504
505resource_node_start: STR
506 {
507 if (curres != NULL && isitme($1))
508 mynode = true;
509 }
510 ;
511
512resource_node_entries:
513 |
514 resource_node_entries resource_node_entry
515 ;
516
517resource_node_entry:
518 name_statement
519 |
520 local_statement
521 |
522 remote_statement
523 ;
524
525remote_statement: REMOTE STR
526 {
527 assert(depth == 2);
528 if (mynode) {
529 assert(curres != NULL);
530 if (strlcpy(curres->hr_remoteaddr, $2,
531 sizeof(curres->hr_remoteaddr)) >=
532 sizeof(curres->hr_remoteaddr)) {
533 errx(EX_CONFIG, "remote argument too long");
534 }
535 }
536 }
537 ;