parse.y revision 216722
1204076Spjd%{
2204076Spjd/*-
3204076Spjd * Copyright (c) 2009-2010 The FreeBSD Foundation
4204076Spjd * All rights reserved.
5204076Spjd *
6204076Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from
7204076Spjd * the FreeBSD Foundation.
8204076Spjd *
9204076Spjd * Redistribution and use in source and binary forms, with or without
10204076Spjd * modification, are permitted provided that the following conditions
11204076Spjd * are met:
12204076Spjd * 1. Redistributions of source code must retain the above copyright
13204076Spjd *    notice, this list of conditions and the following disclaimer.
14204076Spjd * 2. Redistributions in binary form must reproduce the above copyright
15204076Spjd *    notice, this list of conditions and the following disclaimer in the
16204076Spjd *    documentation and/or other materials provided with the distribution.
17204076Spjd *
18204076Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21204076Spjd * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28204076Spjd * SUCH DAMAGE.
29204076Spjd *
30204076Spjd * $FreeBSD: head/sbin/hastd/parse.y 216722 2010-12-26 19:08:41Z pjd $
31204076Spjd */
32204076Spjd
33204076Spjd#include <sys/param.h>	/* MAXHOSTNAMELEN */
34204076Spjd#include <sys/queue.h>
35204076Spjd#include <sys/sysctl.h>
36204076Spjd
37204076Spjd#include <arpa/inet.h>
38204076Spjd
39204076Spjd#include <assert.h>
40204076Spjd#include <err.h>
41204076Spjd#include <stdio.h>
42204076Spjd#include <string.h>
43204076Spjd#include <sysexits.h>
44204076Spjd#include <unistd.h>
45204076Spjd
46210883Spjd#include <pjdlog.h>
47210883Spjd
48204076Spjd#include "hast.h"
49204076Spjd
50204076Spjdextern int depth;
51204076Spjdextern int lineno;
52204076Spjd
53204076Spjdextern FILE *yyin;
54204076Spjdextern char *yytext;
55204076Spjd
56210883Spjdstatic struct hastd_config *lconfig;
57204076Spjdstatic struct hast_resource *curres;
58216721Spjdstatic bool mynode, hadmynode;
59204076Spjd
60204076Spjdstatic char depth0_control[HAST_ADDRSIZE];
61204076Spjdstatic char depth0_listen[HAST_ADDRSIZE];
62204076Spjdstatic int depth0_replication;
63207371Spjdstatic int depth0_timeout;
64211886Spjdstatic char depth0_exec[PATH_MAX];
65204076Spjd
66204076Spjdstatic char depth1_provname[PATH_MAX];
67204076Spjdstatic char depth1_localpath[PATH_MAX];
68204076Spjd
69210883Spjdextern void yyrestart(FILE *);
70210883Spjd
71210883Spjdstatic int
72204076Spjdisitme(const char *name)
73204076Spjd{
74204076Spjd	char buf[MAXHOSTNAMELEN];
75204076Spjd	char *pos;
76204076Spjd	size_t bufsize;
77204076Spjd
78204076Spjd	/*
79204076Spjd	 * First check if the give name matches our full hostname.
80204076Spjd	 */
81210883Spjd	if (gethostname(buf, sizeof(buf)) < 0) {
82210883Spjd		pjdlog_errno(LOG_ERR, "gethostname() failed");
83210883Spjd		return (-1);
84210883Spjd	}
85204076Spjd	if (strcmp(buf, name) == 0)
86210883Spjd		return (1);
87204076Spjd
88204076Spjd	/*
89204076Spjd	 * Now check if it matches first part of the host name.
90204076Spjd	 */
91204076Spjd	pos = strchr(buf, '.');
92204076Spjd	if (pos != NULL && pos != buf && strncmp(buf, name, pos - buf) == 0)
93210883Spjd		return (1);
94204076Spjd
95204076Spjd	/*
96204076Spjd	 * At the end check if name is equal to our host's UUID.
97204076Spjd	 */
98204076Spjd	bufsize = sizeof(buf);
99210883Spjd	if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) {
100210883Spjd		pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed");
101210883Spjd		return (-1);
102210883Spjd	}
103204076Spjd	if (strcasecmp(buf, name) == 0)
104210883Spjd		return (1);
105204076Spjd
106204076Spjd	/*
107204076Spjd	 * Looks like this isn't about us.
108204076Spjd	 */
109210883Spjd	return (0);
110204076Spjd}
111204076Spjd
112216721Spjdstatic int
113216721Spjdnode_names(char **namesp)
114216721Spjd{
115216721Spjd	static char names[MAXHOSTNAMELEN * 3];
116216721Spjd	char buf[MAXHOSTNAMELEN];
117216721Spjd	char *pos;
118216721Spjd	size_t bufsize;
119216721Spjd
120216721Spjd	if (gethostname(buf, sizeof(buf)) < 0) {
121216721Spjd		pjdlog_errno(LOG_ERR, "gethostname() failed");
122216721Spjd		return (-1);
123216721Spjd	}
124216721Spjd
125216721Spjd	/* First component of the host name. */
126216721Spjd	pos = strchr(buf, '.');
127216721Spjd	if (pos != NULL && pos != buf) {
128216721Spjd		(void)strlcpy(names, buf, MIN((size_t)(pos - buf + 1),
129216721Spjd		    sizeof(names)));
130216721Spjd		(void)strlcat(names, ", ", sizeof(names));
131216721Spjd	}
132216721Spjd
133216721Spjd	/* Full host name. */
134216721Spjd	(void)strlcat(names, buf, sizeof(names));
135216721Spjd	(void)strlcat(names, ", ", sizeof(names));
136216721Spjd
137216721Spjd	/* Host UUID. */
138216721Spjd	bufsize = sizeof(buf);
139216721Spjd	if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) {
140216721Spjd		pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed");
141216721Spjd		return (-1);
142216721Spjd	}
143216721Spjd	(void)strlcat(names, buf, sizeof(names));
144216721Spjd
145216721Spjd	*namesp = names;
146216721Spjd
147216721Spjd	return (0);
148216721Spjd}
149216721Spjd
150204076Spjdvoid
151204076Spjdyyerror(const char *str)
152204076Spjd{
153204076Spjd
154210883Spjd	pjdlog_error("Unable to parse configuration file at line %d near '%s': %s",
155204076Spjd	    lineno, yytext, str);
156204076Spjd}
157204076Spjd
158204076Spjdstruct hastd_config *
159210883Spjdyy_config_parse(const char *config, bool exitonerror)
160204076Spjd{
161204076Spjd	int ret;
162204076Spjd
163204076Spjd	curres = NULL;
164204076Spjd	mynode = false;
165210883Spjd	depth = 0;
166210883Spjd	lineno = 0;
167204076Spjd
168207371Spjd	depth0_timeout = HAST_TIMEOUT;
169204076Spjd	depth0_replication = HAST_REPLICATION_MEMSYNC;
170204076Spjd	strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control));
171204076Spjd	strlcpy(depth0_listen, HASTD_LISTEN, sizeof(depth0_listen));
172211886Spjd	depth0_exec[0] = '\0';
173204076Spjd
174210883Spjd	lconfig = calloc(1, sizeof(*lconfig));
175210883Spjd	if (lconfig == NULL) {
176210883Spjd		pjdlog_error("Unable to allocate memory for configuration.");
177210883Spjd		if (exitonerror)
178210883Spjd			exit(EX_TEMPFAIL);
179210883Spjd		return (NULL);
180210883Spjd	}
181204076Spjd
182210883Spjd	TAILQ_INIT(&lconfig->hc_resources);
183210883Spjd
184204076Spjd	yyin = fopen(config, "r");
185210883Spjd	if (yyin == NULL) {
186210883Spjd		pjdlog_errno(LOG_ERR, "Unable to open configuration file %s",
187210883Spjd		    config);
188210883Spjd		yy_config_free(lconfig);
189210883Spjd		if (exitonerror)
190210883Spjd			exit(EX_OSFILE);
191210883Spjd		return (NULL);
192210883Spjd	}
193210883Spjd	yyrestart(yyin);
194204076Spjd	ret = yyparse();
195204076Spjd	fclose(yyin);
196204076Spjd	if (ret != 0) {
197210883Spjd		yy_config_free(lconfig);
198210883Spjd		if (exitonerror)
199210883Spjd			exit(EX_CONFIG);
200210883Spjd		return (NULL);
201204076Spjd	}
202204076Spjd
203204076Spjd	/*
204204076Spjd	 * Let's see if everything is set up.
205204076Spjd	 */
206210883Spjd	if (lconfig->hc_controladdr[0] == '\0') {
207210883Spjd		strlcpy(lconfig->hc_controladdr, depth0_control,
208210883Spjd		    sizeof(lconfig->hc_controladdr));
209204076Spjd	}
210210883Spjd	if (lconfig->hc_listenaddr[0] == '\0') {
211210883Spjd		strlcpy(lconfig->hc_listenaddr, depth0_listen,
212210883Spjd		    sizeof(lconfig->hc_listenaddr));
213204076Spjd	}
214210883Spjd	TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) {
215204076Spjd		assert(curres->hr_provname[0] != '\0');
216204076Spjd		assert(curres->hr_localpath[0] != '\0');
217204076Spjd		assert(curres->hr_remoteaddr[0] != '\0');
218204076Spjd
219204076Spjd		if (curres->hr_replication == -1) {
220204076Spjd			/*
221204076Spjd			 * Replication is not set at resource-level.
222204076Spjd			 * Use global or default setting.
223204076Spjd			 */
224204076Spjd			curres->hr_replication = depth0_replication;
225204076Spjd		}
226207371Spjd		if (curres->hr_timeout == -1) {
227207371Spjd			/*
228207371Spjd			 * Timeout is not set at resource-level.
229207371Spjd			 * Use global or default setting.
230207371Spjd			 */
231207371Spjd			curres->hr_timeout = depth0_timeout;
232207371Spjd		}
233211886Spjd		if (curres->hr_exec[0] == '\0') {
234211886Spjd			/*
235211886Spjd			 * Exec is not set at resource-level.
236211886Spjd			 * Use global or default setting.
237211886Spjd			 */
238211886Spjd			strlcpy(curres->hr_exec, depth0_exec,
239211886Spjd			    sizeof(curres->hr_exec));
240211886Spjd		}
241204076Spjd	}
242204076Spjd
243210883Spjd	return (lconfig);
244204076Spjd}
245204076Spjd
246204076Spjdvoid
247204076Spjdyy_config_free(struct hastd_config *config)
248204076Spjd{
249204076Spjd	struct hast_resource *res;
250204076Spjd
251204076Spjd	while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) {
252204076Spjd		TAILQ_REMOVE(&config->hc_resources, res, hr_next);
253204076Spjd		free(res);
254204076Spjd	}
255210883Spjd	free(config);
256204076Spjd}
257204076Spjd%}
258204076Spjd
259211886Spjd%token CONTROL LISTEN PORT REPLICATION TIMEOUT EXEC EXTENTSIZE RESOURCE NAME LOCAL REMOTE ON
260204076Spjd%token FULLSYNC MEMSYNC ASYNC
261204076Spjd%token NUM STR OB CB
262204076Spjd
263204076Spjd%type <num> replication_type
264204076Spjd
265204076Spjd%union
266204076Spjd{
267204076Spjd	int num;
268204076Spjd	char *str;
269204076Spjd}
270204076Spjd
271204076Spjd%token <num> NUM
272204076Spjd%token <str> STR
273204076Spjd
274204076Spjd%%
275204076Spjd
276204076Spjdstatements:
277204076Spjd	|
278204076Spjd	statements statement
279204076Spjd	;
280204076Spjd
281204076Spjdstatement:
282204076Spjd	control_statement
283204076Spjd	|
284204076Spjd	listen_statement
285204076Spjd	|
286204076Spjd	replication_statement
287204076Spjd	|
288207371Spjd	timeout_statement
289207371Spjd	|
290211886Spjd	exec_statement
291211886Spjd	|
292204076Spjd	node_statement
293204076Spjd	|
294204076Spjd	resource_statement
295204076Spjd	;
296204076Spjd
297204076Spjdcontrol_statement:	CONTROL STR
298204076Spjd	{
299204076Spjd		switch (depth) {
300204076Spjd		case 0:
301204076Spjd			if (strlcpy(depth0_control, $2,
302204076Spjd			    sizeof(depth0_control)) >=
303204076Spjd			    sizeof(depth0_control)) {
304210883Spjd				pjdlog_error("control argument is too long.");
305214274Spjd				free($2);
306210883Spjd				return (1);
307204076Spjd			}
308204076Spjd			break;
309204076Spjd		case 1:
310211883Spjd			if (!mynode)
311211883Spjd				break;
312211883Spjd			if (strlcpy(lconfig->hc_controladdr, $2,
313211883Spjd			    sizeof(lconfig->hc_controladdr)) >=
314211883Spjd			    sizeof(lconfig->hc_controladdr)) {
315211883Spjd				pjdlog_error("control argument is too long.");
316214274Spjd				free($2);
317211883Spjd				return (1);
318204076Spjd			}
319204076Spjd			break;
320204076Spjd		default:
321204076Spjd			assert(!"control at wrong depth level");
322204076Spjd		}
323214274Spjd		free($2);
324204076Spjd	}
325204076Spjd	;
326204076Spjd
327204076Spjdlisten_statement:	LISTEN STR
328204076Spjd	{
329204076Spjd		switch (depth) {
330204076Spjd		case 0:
331204076Spjd			if (strlcpy(depth0_listen, $2,
332204076Spjd			    sizeof(depth0_listen)) >=
333204076Spjd			    sizeof(depth0_listen)) {
334210883Spjd				pjdlog_error("listen argument is too long.");
335214274Spjd				free($2);
336210883Spjd				return (1);
337204076Spjd			}
338204076Spjd			break;
339204076Spjd		case 1:
340211883Spjd			if (!mynode)
341211883Spjd				break;
342211883Spjd			if (strlcpy(lconfig->hc_listenaddr, $2,
343211883Spjd			    sizeof(lconfig->hc_listenaddr)) >=
344211883Spjd			    sizeof(lconfig->hc_listenaddr)) {
345211883Spjd				pjdlog_error("listen argument is too long.");
346214274Spjd				free($2);
347211883Spjd				return (1);
348204076Spjd			}
349204076Spjd			break;
350204076Spjd		default:
351204076Spjd			assert(!"listen at wrong depth level");
352204076Spjd		}
353214274Spjd		free($2);
354204076Spjd	}
355204076Spjd	;
356204076Spjd
357204076Spjdreplication_statement:	REPLICATION replication_type
358204076Spjd	{
359204076Spjd		switch (depth) {
360204076Spjd		case 0:
361204076Spjd			depth0_replication = $2;
362204076Spjd			break;
363204076Spjd		case 1:
364204076Spjd			if (curres != NULL)
365204076Spjd				curres->hr_replication = $2;
366204076Spjd			break;
367204076Spjd		default:
368204076Spjd			assert(!"replication at wrong depth level");
369204076Spjd		}
370204076Spjd	}
371204076Spjd	;
372204076Spjd
373204076Spjdreplication_type:
374204076Spjd	FULLSYNC	{ $$ = HAST_REPLICATION_FULLSYNC; }
375204076Spjd	|
376204076Spjd	MEMSYNC		{ $$ = HAST_REPLICATION_MEMSYNC; }
377204076Spjd	|
378204076Spjd	ASYNC		{ $$ = HAST_REPLICATION_ASYNC; }
379204076Spjd	;
380204076Spjd
381207371Spjdtimeout_statement:	TIMEOUT NUM
382207371Spjd	{
383207371Spjd		switch (depth) {
384207371Spjd		case 0:
385207371Spjd			depth0_timeout = $2;
386207371Spjd			break;
387207371Spjd		case 1:
388207371Spjd			if (curres != NULL)
389207371Spjd				curres->hr_timeout = $2;
390207371Spjd			break;
391207371Spjd		default:
392207371Spjd			assert(!"timeout at wrong depth level");
393207371Spjd		}
394207371Spjd	}
395207371Spjd	;
396207371Spjd
397211886Spjdexec_statement:		EXEC STR
398211886Spjd	{
399211886Spjd		switch (depth) {
400211886Spjd		case 0:
401211886Spjd			if (strlcpy(depth0_exec, $2, sizeof(depth0_exec)) >=
402211886Spjd			    sizeof(depth0_exec)) {
403211886Spjd				pjdlog_error("Exec path is too long.");
404214274Spjd				free($2);
405211886Spjd				return (1);
406211886Spjd			}
407211886Spjd			break;
408211886Spjd		case 1:
409211886Spjd			if (curres == NULL)
410211886Spjd				break;
411211886Spjd			if (strlcpy(curres->hr_exec, $2,
412211886Spjd			    sizeof(curres->hr_exec)) >=
413211886Spjd			    sizeof(curres->hr_exec)) {
414211886Spjd				pjdlog_error("Exec path is too long.");
415214274Spjd				free($2);
416211886Spjd				return (1);
417211886Spjd			}
418211886Spjd			break;
419211886Spjd		default:
420211886Spjd			assert(!"exec at wrong depth level");
421211886Spjd		}
422214274Spjd		free($2);
423211886Spjd	}
424211886Spjd	;
425211886Spjd
426204076Spjdnode_statement:		ON node_start OB node_entries CB
427204076Spjd	{
428204076Spjd		mynode = false;
429204076Spjd	}
430204076Spjd	;
431204076Spjd
432204076Spjdnode_start:	STR
433204076Spjd	{
434210883Spjd		switch (isitme($1)) {
435210883Spjd		case -1:
436214274Spjd			free($1);
437210883Spjd			return (1);
438210883Spjd		case 0:
439210883Spjd			break;
440210883Spjd		case 1:
441204076Spjd			mynode = true;
442210883Spjd			break;
443210883Spjd		default:
444210883Spjd			assert(!"invalid isitme() return value");
445210883Spjd		}
446214274Spjd		free($1);
447204076Spjd	}
448204076Spjd	;
449204076Spjd
450204076Spjdnode_entries:
451204076Spjd	|
452204076Spjd	node_entries node_entry
453204076Spjd	;
454204076Spjd
455204076Spjdnode_entry:
456204076Spjd	control_statement
457204076Spjd	|
458204076Spjd	listen_statement
459204076Spjd	;
460204076Spjd
461204076Spjdresource_statement:	RESOURCE resource_start OB resource_entries CB
462204076Spjd	{
463204076Spjd		if (curres != NULL) {
464204076Spjd			/*
465216721Spjd			 * There must be section for this node, at least with
466216721Spjd			 * remote address configuration.
467216721Spjd			 */
468216721Spjd			if (!hadmynode) {
469216721Spjd				char *names;
470216721Spjd
471216721Spjd				if (node_names(&names) != 0)
472216721Spjd					return (1);
473216721Spjd				pjdlog_error("No resource %s configuration for this node (acceptable node names: %s).",
474216721Spjd				    curres->hr_name, names);
475216721Spjd				return (1);
476216721Spjd			}
477216721Spjd
478216721Spjd			/*
479204076Spjd			 * Let's see there are some resource-level settings
480204076Spjd			 * that we can use for node-level settings.
481204076Spjd			 */
482204076Spjd			if (curres->hr_provname[0] == '\0' &&
483204076Spjd			    depth1_provname[0] != '\0') {
484204076Spjd				/*
485204076Spjd				 * Provider name is not set at node-level,
486204076Spjd				 * but is set at resource-level, use it.
487204076Spjd				 */
488204076Spjd				strlcpy(curres->hr_provname, depth1_provname,
489204076Spjd				    sizeof(curres->hr_provname));
490204076Spjd			}
491204076Spjd			if (curres->hr_localpath[0] == '\0' &&
492204076Spjd			    depth1_localpath[0] != '\0') {
493204076Spjd				/*
494204076Spjd				 * Path to local provider is not set at
495204076Spjd				 * node-level, but is set at resource-level,
496204076Spjd				 * use it.
497204076Spjd				 */
498204076Spjd				strlcpy(curres->hr_localpath, depth1_localpath,
499204076Spjd				    sizeof(curres->hr_localpath));
500204076Spjd			}
501204076Spjd
502204076Spjd			/*
503204076Spjd			 * If provider name is not given, use resource name
504204076Spjd			 * as provider name.
505204076Spjd			 */
506204076Spjd			if (curres->hr_provname[0] == '\0') {
507204076Spjd				strlcpy(curres->hr_provname, curres->hr_name,
508204076Spjd				    sizeof(curres->hr_provname));
509204076Spjd			}
510204076Spjd
511204076Spjd			/*
512204076Spjd			 * Remote address has to be configured at this point.
513204076Spjd			 */
514204076Spjd			if (curres->hr_remoteaddr[0] == '\0') {
515210883Spjd				pjdlog_error("Remote address not configured for resource %s.",
516204076Spjd				    curres->hr_name);
517210883Spjd				return (1);
518204076Spjd			}
519204076Spjd			/*
520204076Spjd			 * Path to local provider has to be configured at this
521204076Spjd			 * point.
522204076Spjd			 */
523204076Spjd			if (curres->hr_localpath[0] == '\0') {
524210883Spjd				pjdlog_error("Path to local component not configured for resource %s.",
525204076Spjd				    curres->hr_name);
526210883Spjd				return (1);
527204076Spjd			}
528204076Spjd
529204076Spjd			/* Put it onto resource list. */
530210883Spjd			TAILQ_INSERT_TAIL(&lconfig->hc_resources, curres, hr_next);
531204076Spjd			curres = NULL;
532204076Spjd		}
533204076Spjd	}
534204076Spjd	;
535204076Spjd
536204076Spjdresource_start:	STR
537204076Spjd	{
538216722Spjd		/* Check if there is no duplicate entry. */
539216722Spjd		TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) {
540216722Spjd			if (strcmp(curres->hr_name, $1) == 0) {
541216722Spjd				pjdlog_error("Resource %s configured more than once.",
542216722Spjd				    curres->hr_name);
543216722Spjd				free($1);
544216722Spjd				return (1);
545216722Spjd			}
546216722Spjd		}
547216722Spjd
548204076Spjd		/*
549204076Spjd		 * Clear those, so we can tell if they were set at
550204076Spjd		 * resource-level or not.
551204076Spjd		 */
552204076Spjd		depth1_provname[0] = '\0';
553204076Spjd		depth1_localpath[0] = '\0';
554216721Spjd		hadmynode = false;
555204076Spjd
556204076Spjd		curres = calloc(1, sizeof(*curres));
557204076Spjd		if (curres == NULL) {
558210883Spjd			pjdlog_error("Unable to allocate memory for resource.");
559214274Spjd			free($1);
560210883Spjd			return (1);
561204076Spjd		}
562204076Spjd		if (strlcpy(curres->hr_name, $1,
563204076Spjd		    sizeof(curres->hr_name)) >=
564204076Spjd		    sizeof(curres->hr_name)) {
565210883Spjd			pjdlog_error("Resource name is too long.");
566214274Spjd			free($1);
567210883Spjd			return (1);
568204076Spjd		}
569214274Spjd		free($1);
570204076Spjd		curres->hr_role = HAST_ROLE_INIT;
571204076Spjd		curres->hr_previous_role = HAST_ROLE_INIT;
572204076Spjd		curres->hr_replication = -1;
573207371Spjd		curres->hr_timeout = -1;
574211886Spjd		curres->hr_exec[0] = '\0';
575204076Spjd		curres->hr_provname[0] = '\0';
576204076Spjd		curres->hr_localpath[0] = '\0';
577204076Spjd		curres->hr_localfd = -1;
578204076Spjd		curres->hr_remoteaddr[0] = '\0';
579204076Spjd		curres->hr_ggateunit = -1;
580204076Spjd	}
581204076Spjd	;
582204076Spjd
583204076Spjdresource_entries:
584204076Spjd	|
585204076Spjd	resource_entries resource_entry
586204076Spjd	;
587204076Spjd
588204076Spjdresource_entry:
589204076Spjd	replication_statement
590204076Spjd	|
591207371Spjd	timeout_statement
592207371Spjd	|
593211886Spjd	exec_statement
594211886Spjd	|
595204076Spjd	name_statement
596204076Spjd	|
597204076Spjd	local_statement
598204076Spjd	|
599204076Spjd	resource_node_statement
600204076Spjd	;
601204076Spjd
602204076Spjdname_statement:		NAME STR
603204076Spjd	{
604204076Spjd		switch (depth) {
605204076Spjd		case 1:
606204076Spjd			if (strlcpy(depth1_provname, $2,
607204076Spjd			    sizeof(depth1_provname)) >=
608204076Spjd			    sizeof(depth1_provname)) {
609210883Spjd				pjdlog_error("name argument is too long.");
610214274Spjd				free($2);
611210883Spjd				return (1);
612204076Spjd			}
613204076Spjd			break;
614204076Spjd		case 2:
615211883Spjd			if (!mynode)
616211883Spjd				break;
617211883Spjd			assert(curres != NULL);
618211883Spjd			if (strlcpy(curres->hr_provname, $2,
619211883Spjd			    sizeof(curres->hr_provname)) >=
620211883Spjd			    sizeof(curres->hr_provname)) {
621211883Spjd				pjdlog_error("name argument is too long.");
622214274Spjd				free($2);
623211883Spjd				return (1);
624204076Spjd			}
625204076Spjd			break;
626204076Spjd		default:
627204076Spjd			assert(!"name at wrong depth level");
628204076Spjd		}
629214274Spjd		free($2);
630204076Spjd	}
631204076Spjd	;
632204076Spjd
633204076Spjdlocal_statement:	LOCAL STR
634204076Spjd	{
635204076Spjd		switch (depth) {
636204076Spjd		case 1:
637204076Spjd			if (strlcpy(depth1_localpath, $2,
638204076Spjd			    sizeof(depth1_localpath)) >=
639204076Spjd			    sizeof(depth1_localpath)) {
640210883Spjd				pjdlog_error("local argument is too long.");
641214274Spjd				free($2);
642210883Spjd				return (1);
643204076Spjd			}
644204076Spjd			break;
645204076Spjd		case 2:
646211883Spjd			if (!mynode)
647211883Spjd				break;
648211883Spjd			assert(curres != NULL);
649211883Spjd			if (strlcpy(curres->hr_localpath, $2,
650211883Spjd			    sizeof(curres->hr_localpath)) >=
651211883Spjd			    sizeof(curres->hr_localpath)) {
652211883Spjd				pjdlog_error("local argument is too long.");
653214274Spjd				free($2);
654211883Spjd				return (1);
655204076Spjd			}
656204076Spjd			break;
657204076Spjd		default:
658204076Spjd			assert(!"local at wrong depth level");
659204076Spjd		}
660214274Spjd		free($2);
661204076Spjd	}
662204076Spjd	;
663204076Spjd
664204076Spjdresource_node_statement:ON resource_node_start OB resource_node_entries CB
665204076Spjd	{
666204076Spjd		mynode = false;
667204076Spjd	}
668204076Spjd	;
669204076Spjd
670204076Spjdresource_node_start:	STR
671204076Spjd	{
672210883Spjd		if (curres != NULL) {
673210883Spjd			switch (isitme($1)) {
674210883Spjd			case -1:
675214274Spjd				free($1);
676210883Spjd				return (1);
677210883Spjd			case 0:
678210883Spjd				break;
679210883Spjd			case 1:
680216721Spjd				mynode = hadmynode = true;
681210883Spjd				break;
682210883Spjd			default:
683210883Spjd				assert(!"invalid isitme() return value");
684210883Spjd			}
685210883Spjd		}
686214274Spjd		free($1);
687204076Spjd	}
688204076Spjd	;
689204076Spjd
690204076Spjdresource_node_entries:
691204076Spjd	|
692204076Spjd	resource_node_entries resource_node_entry
693204076Spjd	;
694204076Spjd
695204076Spjdresource_node_entry:
696204076Spjd	name_statement
697204076Spjd	|
698204076Spjd	local_statement
699204076Spjd	|
700204076Spjd	remote_statement
701204076Spjd	;
702204076Spjd
703204076Spjdremote_statement:	REMOTE STR
704204076Spjd	{
705204076Spjd		assert(depth == 2);
706204076Spjd		if (mynode) {
707204076Spjd			assert(curres != NULL);
708204076Spjd			if (strlcpy(curres->hr_remoteaddr, $2,
709204076Spjd			    sizeof(curres->hr_remoteaddr)) >=
710204076Spjd			    sizeof(curres->hr_remoteaddr)) {
711210883Spjd				pjdlog_error("remote argument is too long.");
712214274Spjd				free($2);
713210883Spjd				return (1);
714204076Spjd			}
715204076Spjd		}
716214274Spjd		free($2);
717204076Spjd	}
718204076Spjd	;
719