Prepare configuration parsing code to be called multiple times:
- Don't exit on errors if not requested. - Don't keep configuration in global variable, but allocate memory for configuration. - Call yyrestart() before yyparse() so that on error in configuration file we will start from the begining next time and not from the place we left of. MFC after: 1 month
This commit is contained in:
parent
a00829bb71
commit
bbbb114cda
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=210883
@ -183,7 +183,7 @@ struct hast_resource {
|
|||||||
TAILQ_ENTRY(hast_resource) hr_next;
|
TAILQ_ENTRY(hast_resource) hr_next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hastd_config *yy_config_parse(const char *config);
|
struct hastd_config *yy_config_parse(const char *config, bool exitonerror);
|
||||||
void yy_config_free(struct hastd_config *config);
|
void yy_config_free(struct hastd_config *config);
|
||||||
|
|
||||||
void yyerror(const char *);
|
void yyerror(const char *);
|
||||||
|
@ -493,7 +493,7 @@ main(int argc, char *argv[])
|
|||||||
pjdlog_errno(LOG_WARNING, "Unable to open or create pidfile");
|
pjdlog_errno(LOG_WARNING, "Unable to open or create pidfile");
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg = yy_config_parse(cfgpath);
|
cfg = yy_config_parse(cfgpath, true);
|
||||||
assert(cfg != NULL);
|
assert(cfg != NULL);
|
||||||
|
|
||||||
signal(SIGHUP, sighandler);
|
signal(SIGHUP, sighandler);
|
||||||
|
@ -43,6 +43,8 @@
|
|||||||
#include <sysexits.h>
|
#include <sysexits.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <pjdlog.h>
|
||||||
|
|
||||||
#include "hast.h"
|
#include "hast.h"
|
||||||
|
|
||||||
extern int depth;
|
extern int depth;
|
||||||
@ -51,7 +53,7 @@ extern int lineno;
|
|||||||
extern FILE *yyin;
|
extern FILE *yyin;
|
||||||
extern char *yytext;
|
extern char *yytext;
|
||||||
|
|
||||||
static struct hastd_config lconfig;
|
static struct hastd_config *lconfig;
|
||||||
static struct hast_resource *curres;
|
static struct hast_resource *curres;
|
||||||
static bool mynode;
|
static bool mynode;
|
||||||
|
|
||||||
@ -63,7 +65,9 @@ static int depth0_timeout;
|
|||||||
static char depth1_provname[PATH_MAX];
|
static char depth1_provname[PATH_MAX];
|
||||||
static char depth1_localpath[PATH_MAX];
|
static char depth1_localpath[PATH_MAX];
|
||||||
|
|
||||||
static bool
|
extern void yyrestart(FILE *);
|
||||||
|
|
||||||
|
static int
|
||||||
isitme(const char *name)
|
isitme(const char *name)
|
||||||
{
|
{
|
||||||
char buf[MAXHOSTNAMELEN];
|
char buf[MAXHOSTNAMELEN];
|
||||||
@ -73,78 +77,101 @@ isitme(const char *name)
|
|||||||
/*
|
/*
|
||||||
* First check if the give name matches our full hostname.
|
* First check if the give name matches our full hostname.
|
||||||
*/
|
*/
|
||||||
if (gethostname(buf, sizeof(buf)) < 0)
|
if (gethostname(buf, sizeof(buf)) < 0) {
|
||||||
err(EX_OSERR, "gethostname() failed");
|
pjdlog_errno(LOG_ERR, "gethostname() failed");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
if (strcmp(buf, name) == 0)
|
if (strcmp(buf, name) == 0)
|
||||||
return (true);
|
return (1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now check if it matches first part of the host name.
|
* Now check if it matches first part of the host name.
|
||||||
*/
|
*/
|
||||||
pos = strchr(buf, '.');
|
pos = strchr(buf, '.');
|
||||||
if (pos != NULL && pos != buf && strncmp(buf, name, pos - buf) == 0)
|
if (pos != NULL && pos != buf && strncmp(buf, name, pos - buf) == 0)
|
||||||
return (true);
|
return (1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At the end check if name is equal to our host's UUID.
|
* At the end check if name is equal to our host's UUID.
|
||||||
*/
|
*/
|
||||||
bufsize = sizeof(buf);
|
bufsize = sizeof(buf);
|
||||||
if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0)
|
if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) {
|
||||||
err(EX_OSERR, "sysctlbyname(kern.hostuuid) failed");
|
pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed");
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
if (strcasecmp(buf, name) == 0)
|
if (strcasecmp(buf, name) == 0)
|
||||||
return (true);
|
return (1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Looks like this isn't about us.
|
* Looks like this isn't about us.
|
||||||
*/
|
*/
|
||||||
return (false);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
yyerror(const char *str)
|
yyerror(const char *str)
|
||||||
{
|
{
|
||||||
|
|
||||||
fprintf(stderr, "error at line %d near '%s': %s\n",
|
pjdlog_error("Unable to parse configuration file at line %d near '%s': %s",
|
||||||
lineno, yytext, str);
|
lineno, yytext, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct hastd_config *
|
struct hastd_config *
|
||||||
yy_config_parse(const char *config)
|
yy_config_parse(const char *config, bool exitonerror)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
curres = NULL;
|
curres = NULL;
|
||||||
mynode = false;
|
mynode = false;
|
||||||
|
depth = 0;
|
||||||
|
lineno = 0;
|
||||||
|
|
||||||
depth0_timeout = HAST_TIMEOUT;
|
depth0_timeout = HAST_TIMEOUT;
|
||||||
depth0_replication = HAST_REPLICATION_MEMSYNC;
|
depth0_replication = HAST_REPLICATION_MEMSYNC;
|
||||||
strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control));
|
strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control));
|
||||||
strlcpy(depth0_listen, HASTD_LISTEN, sizeof(depth0_listen));
|
strlcpy(depth0_listen, HASTD_LISTEN, sizeof(depth0_listen));
|
||||||
|
|
||||||
TAILQ_INIT(&lconfig.hc_resources);
|
lconfig = calloc(1, sizeof(*lconfig));
|
||||||
|
if (lconfig == NULL) {
|
||||||
|
pjdlog_error("Unable to allocate memory for configuration.");
|
||||||
|
if (exitonerror)
|
||||||
|
exit(EX_TEMPFAIL);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
TAILQ_INIT(&lconfig->hc_resources);
|
||||||
|
|
||||||
yyin = fopen(config, "r");
|
yyin = fopen(config, "r");
|
||||||
if (yyin == NULL)
|
if (yyin == NULL) {
|
||||||
err(EX_OSFILE, "cannot open configuration file %s", config);
|
pjdlog_errno(LOG_ERR, "Unable to open configuration file %s",
|
||||||
|
config);
|
||||||
|
yy_config_free(lconfig);
|
||||||
|
if (exitonerror)
|
||||||
|
exit(EX_OSFILE);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
yyrestart(yyin);
|
||||||
ret = yyparse();
|
ret = yyparse();
|
||||||
fclose(yyin);
|
fclose(yyin);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
yy_config_free(&lconfig);
|
yy_config_free(lconfig);
|
||||||
exit(EX_CONFIG);
|
if (exitonerror)
|
||||||
|
exit(EX_CONFIG);
|
||||||
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let's see if everything is set up.
|
* Let's see if everything is set up.
|
||||||
*/
|
*/
|
||||||
if (lconfig.hc_controladdr[0] == '\0') {
|
if (lconfig->hc_controladdr[0] == '\0') {
|
||||||
strlcpy(lconfig.hc_controladdr, depth0_control,
|
strlcpy(lconfig->hc_controladdr, depth0_control,
|
||||||
sizeof(lconfig.hc_controladdr));
|
sizeof(lconfig->hc_controladdr));
|
||||||
}
|
}
|
||||||
if (lconfig.hc_listenaddr[0] == '\0') {
|
if (lconfig->hc_listenaddr[0] == '\0') {
|
||||||
strlcpy(lconfig.hc_listenaddr, depth0_listen,
|
strlcpy(lconfig->hc_listenaddr, depth0_listen,
|
||||||
sizeof(lconfig.hc_listenaddr));
|
sizeof(lconfig->hc_listenaddr));
|
||||||
}
|
}
|
||||||
TAILQ_FOREACH(curres, &lconfig.hc_resources, hr_next) {
|
TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) {
|
||||||
assert(curres->hr_provname[0] != '\0');
|
assert(curres->hr_provname[0] != '\0');
|
||||||
assert(curres->hr_localpath[0] != '\0');
|
assert(curres->hr_localpath[0] != '\0');
|
||||||
assert(curres->hr_remoteaddr[0] != '\0');
|
assert(curres->hr_remoteaddr[0] != '\0');
|
||||||
@ -165,7 +192,7 @@ yy_config_parse(const char *config)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (&lconfig);
|
return (lconfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -177,6 +204,7 @@ yy_config_free(struct hastd_config *config)
|
|||||||
TAILQ_REMOVE(&config->hc_resources, res, hr_next);
|
TAILQ_REMOVE(&config->hc_resources, res, hr_next);
|
||||||
free(res);
|
free(res);
|
||||||
}
|
}
|
||||||
|
free(config);
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
|
|
||||||
@ -223,16 +251,17 @@ control_statement: CONTROL STR
|
|||||||
if (strlcpy(depth0_control, $2,
|
if (strlcpy(depth0_control, $2,
|
||||||
sizeof(depth0_control)) >=
|
sizeof(depth0_control)) >=
|
||||||
sizeof(depth0_control)) {
|
sizeof(depth0_control)) {
|
||||||
errx(EX_CONFIG, "control argument too long");
|
pjdlog_error("control argument is too long.");
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (mynode) {
|
if (mynode) {
|
||||||
if (strlcpy(lconfig.hc_controladdr, $2,
|
if (strlcpy(lconfig->hc_controladdr, $2,
|
||||||
sizeof(lconfig.hc_controladdr)) >=
|
sizeof(lconfig->hc_controladdr)) >=
|
||||||
sizeof(lconfig.hc_controladdr)) {
|
sizeof(lconfig->hc_controladdr)) {
|
||||||
errx(EX_CONFIG,
|
pjdlog_error("control argument is too long.");
|
||||||
"control argument too long");
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -249,16 +278,17 @@ listen_statement: LISTEN STR
|
|||||||
if (strlcpy(depth0_listen, $2,
|
if (strlcpy(depth0_listen, $2,
|
||||||
sizeof(depth0_listen)) >=
|
sizeof(depth0_listen)) >=
|
||||||
sizeof(depth0_listen)) {
|
sizeof(depth0_listen)) {
|
||||||
errx(EX_CONFIG, "listen argument too long");
|
pjdlog_error("listen argument is too long.");
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (mynode) {
|
if (mynode) {
|
||||||
if (strlcpy(lconfig.hc_listenaddr, $2,
|
if (strlcpy(lconfig->hc_listenaddr, $2,
|
||||||
sizeof(lconfig.hc_listenaddr)) >=
|
sizeof(lconfig->hc_listenaddr)) >=
|
||||||
sizeof(lconfig.hc_listenaddr)) {
|
sizeof(lconfig->hc_listenaddr)) {
|
||||||
errx(EX_CONFIG,
|
pjdlog_error("listen argument is too long.");
|
||||||
"listen argument too long");
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -316,8 +346,17 @@ node_statement: ON node_start OB node_entries CB
|
|||||||
|
|
||||||
node_start: STR
|
node_start: STR
|
||||||
{
|
{
|
||||||
if (isitme($1))
|
switch (isitme($1)) {
|
||||||
|
case -1:
|
||||||
|
return (1);
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
mynode = true;
|
mynode = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"invalid isitme() return value");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -372,22 +411,22 @@ resource_statement: RESOURCE resource_start OB resource_entries CB
|
|||||||
* Remote address has to be configured at this point.
|
* Remote address has to be configured at this point.
|
||||||
*/
|
*/
|
||||||
if (curres->hr_remoteaddr[0] == '\0') {
|
if (curres->hr_remoteaddr[0] == '\0') {
|
||||||
errx(EX_CONFIG,
|
pjdlog_error("Remote address not configured for resource %s.",
|
||||||
"remote address not configured for resource %s",
|
|
||||||
curres->hr_name);
|
curres->hr_name);
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Path to local provider has to be configured at this
|
* Path to local provider has to be configured at this
|
||||||
* point.
|
* point.
|
||||||
*/
|
*/
|
||||||
if (curres->hr_localpath[0] == '\0') {
|
if (curres->hr_localpath[0] == '\0') {
|
||||||
errx(EX_CONFIG,
|
pjdlog_error("Path to local component not configured for resource %s.",
|
||||||
"path local component not configured for resource %s",
|
|
||||||
curres->hr_name);
|
curres->hr_name);
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Put it onto resource list. */
|
/* Put it onto resource list. */
|
||||||
TAILQ_INSERT_TAIL(&lconfig.hc_resources, curres, hr_next);
|
TAILQ_INSERT_TAIL(&lconfig->hc_resources, curres, hr_next);
|
||||||
curres = NULL;
|
curres = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -404,14 +443,14 @@ resource_start: STR
|
|||||||
|
|
||||||
curres = calloc(1, sizeof(*curres));
|
curres = calloc(1, sizeof(*curres));
|
||||||
if (curres == NULL) {
|
if (curres == NULL) {
|
||||||
errx(EX_TEMPFAIL,
|
pjdlog_error("Unable to allocate memory for resource.");
|
||||||
"cannot allocate memory for resource");
|
return (1);
|
||||||
}
|
}
|
||||||
if (strlcpy(curres->hr_name, $1,
|
if (strlcpy(curres->hr_name, $1,
|
||||||
sizeof(curres->hr_name)) >=
|
sizeof(curres->hr_name)) >=
|
||||||
sizeof(curres->hr_name)) {
|
sizeof(curres->hr_name)) {
|
||||||
errx(EX_CONFIG,
|
pjdlog_error("Resource name is too long.");
|
||||||
"resource name (%s) too long", $1);
|
return (1);
|
||||||
}
|
}
|
||||||
curres->hr_role = HAST_ROLE_INIT;
|
curres->hr_role = HAST_ROLE_INIT;
|
||||||
curres->hr_previous_role = HAST_ROLE_INIT;
|
curres->hr_previous_role = HAST_ROLE_INIT;
|
||||||
@ -449,7 +488,8 @@ name_statement: NAME STR
|
|||||||
if (strlcpy(depth1_provname, $2,
|
if (strlcpy(depth1_provname, $2,
|
||||||
sizeof(depth1_provname)) >=
|
sizeof(depth1_provname)) >=
|
||||||
sizeof(depth1_provname)) {
|
sizeof(depth1_provname)) {
|
||||||
errx(EX_CONFIG, "name argument too long");
|
pjdlog_error("name argument is too long.");
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
@ -458,8 +498,8 @@ name_statement: NAME STR
|
|||||||
if (strlcpy(curres->hr_provname, $2,
|
if (strlcpy(curres->hr_provname, $2,
|
||||||
sizeof(curres->hr_provname)) >=
|
sizeof(curres->hr_provname)) >=
|
||||||
sizeof(curres->hr_provname)) {
|
sizeof(curres->hr_provname)) {
|
||||||
errx(EX_CONFIG,
|
pjdlog_error("name argument is too long.");
|
||||||
"name argument too long");
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -476,7 +516,8 @@ local_statement: LOCAL STR
|
|||||||
if (strlcpy(depth1_localpath, $2,
|
if (strlcpy(depth1_localpath, $2,
|
||||||
sizeof(depth1_localpath)) >=
|
sizeof(depth1_localpath)) >=
|
||||||
sizeof(depth1_localpath)) {
|
sizeof(depth1_localpath)) {
|
||||||
errx(EX_CONFIG, "local argument too long");
|
pjdlog_error("local argument is too long.");
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
@ -485,8 +526,8 @@ local_statement: LOCAL STR
|
|||||||
if (strlcpy(curres->hr_localpath, $2,
|
if (strlcpy(curres->hr_localpath, $2,
|
||||||
sizeof(curres->hr_localpath)) >=
|
sizeof(curres->hr_localpath)) >=
|
||||||
sizeof(curres->hr_localpath)) {
|
sizeof(curres->hr_localpath)) {
|
||||||
errx(EX_CONFIG,
|
pjdlog_error("local argument is too long.");
|
||||||
"local argument too long");
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -504,8 +545,19 @@ resource_node_statement:ON resource_node_start OB resource_node_entries CB
|
|||||||
|
|
||||||
resource_node_start: STR
|
resource_node_start: STR
|
||||||
{
|
{
|
||||||
if (curres != NULL && isitme($1))
|
if (curres != NULL) {
|
||||||
mynode = true;
|
switch (isitme($1)) {
|
||||||
|
case -1:
|
||||||
|
return (1);
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
mynode = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
assert(!"invalid isitme() return value");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -530,7 +582,8 @@ remote_statement: REMOTE STR
|
|||||||
if (strlcpy(curres->hr_remoteaddr, $2,
|
if (strlcpy(curres->hr_remoteaddr, $2,
|
||||||
sizeof(curres->hr_remoteaddr)) >=
|
sizeof(curres->hr_remoteaddr)) >=
|
||||||
sizeof(curres->hr_remoteaddr)) {
|
sizeof(curres->hr_remoteaddr)) {
|
||||||
errx(EX_CONFIG, "remote argument too long");
|
pjdlog_error("remote argument is too long.");
|
||||||
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user