parse.y revision 220889
1204076Spjd%{ 2204076Spjd/*- 3204076Spjd * Copyright (c) 2009-2010 The FreeBSD Foundation 4219351Spjd * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> 5204076Spjd * All rights reserved. 6204076Spjd * 7204076Spjd * This software was developed by Pawel Jakub Dawidek under sponsorship from 8204076Spjd * the FreeBSD Foundation. 9204076Spjd * 10204076Spjd * Redistribution and use in source and binary forms, with or without 11204076Spjd * modification, are permitted provided that the following conditions 12204076Spjd * are met: 13204076Spjd * 1. Redistributions of source code must retain the above copyright 14204076Spjd * notice, this list of conditions and the following disclaimer. 15204076Spjd * 2. Redistributions in binary form must reproduce the above copyright 16204076Spjd * notice, this list of conditions and the following disclaimer in the 17204076Spjd * documentation and/or other materials provided with the distribution. 18204076Spjd * 19204076Spjd * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 20204076Spjd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21204076Spjd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22204076Spjd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 23204076Spjd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24204076Spjd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25204076Spjd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26204076Spjd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27204076Spjd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28204076Spjd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29204076Spjd * SUCH DAMAGE. 30204076Spjd * 31204076Spjd * $FreeBSD: head/sbin/hastd/parse.y 220889 2011-04-20 16:36:59Z pjd $ 32204076Spjd */ 33204076Spjd 34204076Spjd#include <sys/param.h> /* MAXHOSTNAMELEN */ 35204076Spjd#include <sys/queue.h> 36204076Spjd#include <sys/sysctl.h> 37204076Spjd 38204076Spjd#include <arpa/inet.h> 39204076Spjd 40204076Spjd#include <assert.h> 41204076Spjd#include <err.h> 42204076Spjd#include <stdio.h> 43204076Spjd#include <string.h> 44204076Spjd#include <sysexits.h> 45204076Spjd#include <unistd.h> 46204076Spjd 47210883Spjd#include <pjdlog.h> 48210883Spjd 49204076Spjd#include "hast.h" 50204076Spjd 51204076Spjdextern int depth; 52204076Spjdextern int lineno; 53204076Spjd 54204076Spjdextern FILE *yyin; 55204076Spjdextern char *yytext; 56204076Spjd 57210883Spjdstatic struct hastd_config *lconfig; 58204076Spjdstatic struct hast_resource *curres; 59216721Spjdstatic bool mynode, hadmynode; 60204076Spjd 61204076Spjdstatic char depth0_control[HAST_ADDRSIZE]; 62204076Spjdstatic char depth0_listen[HAST_ADDRSIZE]; 63204076Spjdstatic int depth0_replication; 64219351Spjdstatic int depth0_checksum; 65219354Spjdstatic int depth0_compression; 66207371Spjdstatic int depth0_timeout; 67211886Spjdstatic char depth0_exec[PATH_MAX]; 68204076Spjd 69204076Spjdstatic char depth1_provname[PATH_MAX]; 70204076Spjdstatic char depth1_localpath[PATH_MAX]; 71204076Spjd 72210883Spjdextern void yyrestart(FILE *); 73210883Spjd 74210883Spjdstatic int 75204076Spjdisitme(const char *name) 76204076Spjd{ 77204076Spjd char buf[MAXHOSTNAMELEN]; 78204076Spjd char *pos; 79204076Spjd size_t bufsize; 80204076Spjd 81204076Spjd /* 82204076Spjd * First check if the give name matches our full hostname. 83204076Spjd */ 84210883Spjd if (gethostname(buf, sizeof(buf)) < 0) { 85210883Spjd pjdlog_errno(LOG_ERR, "gethostname() failed"); 86210883Spjd return (-1); 87210883Spjd } 88204076Spjd if (strcmp(buf, name) == 0) 89210883Spjd return (1); 90204076Spjd 91204076Spjd /* 92204076Spjd * Now check if it matches first part of the host name. 93204076Spjd */ 94204076Spjd pos = strchr(buf, '.'); 95204076Spjd if (pos != NULL && pos != buf && strncmp(buf, name, pos - buf) == 0) 96210883Spjd return (1); 97204076Spjd 98204076Spjd /* 99204076Spjd * At the end check if name is equal to our host's UUID. 100204076Spjd */ 101204076Spjd bufsize = sizeof(buf); 102210883Spjd if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 103210883Spjd pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 104210883Spjd return (-1); 105210883Spjd } 106204076Spjd if (strcasecmp(buf, name) == 0) 107210883Spjd return (1); 108204076Spjd 109204076Spjd /* 110204076Spjd * Looks like this isn't about us. 111204076Spjd */ 112210883Spjd return (0); 113204076Spjd} 114204076Spjd 115216721Spjdstatic int 116216721Spjdnode_names(char **namesp) 117216721Spjd{ 118216721Spjd static char names[MAXHOSTNAMELEN * 3]; 119216721Spjd char buf[MAXHOSTNAMELEN]; 120216721Spjd char *pos; 121216721Spjd size_t bufsize; 122216721Spjd 123216721Spjd if (gethostname(buf, sizeof(buf)) < 0) { 124216721Spjd pjdlog_errno(LOG_ERR, "gethostname() failed"); 125216721Spjd return (-1); 126216721Spjd } 127216721Spjd 128216721Spjd /* First component of the host name. */ 129216721Spjd pos = strchr(buf, '.'); 130216721Spjd if (pos != NULL && pos != buf) { 131216721Spjd (void)strlcpy(names, buf, MIN((size_t)(pos - buf + 1), 132216721Spjd sizeof(names))); 133216721Spjd (void)strlcat(names, ", ", sizeof(names)); 134216721Spjd } 135216721Spjd 136216721Spjd /* Full host name. */ 137216721Spjd (void)strlcat(names, buf, sizeof(names)); 138216721Spjd (void)strlcat(names, ", ", sizeof(names)); 139216721Spjd 140216721Spjd /* Host UUID. */ 141216721Spjd bufsize = sizeof(buf); 142216721Spjd if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 143216721Spjd pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 144216721Spjd return (-1); 145216721Spjd } 146216721Spjd (void)strlcat(names, buf, sizeof(names)); 147216721Spjd 148216721Spjd *namesp = names; 149216721Spjd 150216721Spjd return (0); 151216721Spjd} 152216721Spjd 153204076Spjdvoid 154204076Spjdyyerror(const char *str) 155204076Spjd{ 156204076Spjd 157210883Spjd pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", 158204076Spjd lineno, yytext, str); 159204076Spjd} 160204076Spjd 161204076Spjdstruct hastd_config * 162210883Spjdyy_config_parse(const char *config, bool exitonerror) 163204076Spjd{ 164204076Spjd int ret; 165204076Spjd 166204076Spjd curres = NULL; 167204076Spjd mynode = false; 168210883Spjd depth = 0; 169210883Spjd lineno = 0; 170204076Spjd 171207371Spjd depth0_timeout = HAST_TIMEOUT; 172220573Spjd depth0_replication = HAST_REPLICATION_FULLSYNC; 173219351Spjd depth0_checksum = HAST_CHECKSUM_NONE; 174219354Spjd depth0_compression = HAST_COMPRESSION_HOLE; 175204076Spjd strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control)); 176204076Spjd strlcpy(depth0_listen, HASTD_LISTEN, sizeof(depth0_listen)); 177211886Spjd depth0_exec[0] = '\0'; 178204076Spjd 179210883Spjd lconfig = calloc(1, sizeof(*lconfig)); 180210883Spjd if (lconfig == NULL) { 181210883Spjd pjdlog_error("Unable to allocate memory for configuration."); 182210883Spjd if (exitonerror) 183210883Spjd exit(EX_TEMPFAIL); 184210883Spjd return (NULL); 185210883Spjd } 186204076Spjd 187210883Spjd TAILQ_INIT(&lconfig->hc_resources); 188210883Spjd 189204076Spjd yyin = fopen(config, "r"); 190210883Spjd if (yyin == NULL) { 191210883Spjd pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", 192210883Spjd config); 193210883Spjd yy_config_free(lconfig); 194210883Spjd if (exitonerror) 195210883Spjd exit(EX_OSFILE); 196210883Spjd return (NULL); 197210883Spjd } 198210883Spjd yyrestart(yyin); 199204076Spjd ret = yyparse(); 200204076Spjd fclose(yyin); 201204076Spjd if (ret != 0) { 202210883Spjd yy_config_free(lconfig); 203210883Spjd if (exitonerror) 204210883Spjd exit(EX_CONFIG); 205210883Spjd return (NULL); 206204076Spjd } 207204076Spjd 208204076Spjd /* 209204076Spjd * Let's see if everything is set up. 210204076Spjd */ 211210883Spjd if (lconfig->hc_controladdr[0] == '\0') { 212210883Spjd strlcpy(lconfig->hc_controladdr, depth0_control, 213210883Spjd sizeof(lconfig->hc_controladdr)); 214204076Spjd } 215210883Spjd if (lconfig->hc_listenaddr[0] == '\0') { 216210883Spjd strlcpy(lconfig->hc_listenaddr, depth0_listen, 217210883Spjd sizeof(lconfig->hc_listenaddr)); 218204076Spjd } 219210883Spjd TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 220204076Spjd assert(curres->hr_provname[0] != '\0'); 221204076Spjd assert(curres->hr_localpath[0] != '\0'); 222204076Spjd assert(curres->hr_remoteaddr[0] != '\0'); 223204076Spjd 224204076Spjd if (curres->hr_replication == -1) { 225204076Spjd /* 226204076Spjd * Replication is not set at resource-level. 227204076Spjd * Use global or default setting. 228204076Spjd */ 229204076Spjd curres->hr_replication = depth0_replication; 230204076Spjd } 231220573Spjd if (curres->hr_replication == HAST_REPLICATION_MEMSYNC || 232220573Spjd curres->hr_replication == HAST_REPLICATION_ASYNC) { 233220573Spjd pjdlog_warning("Replication mode \"%s\" is not implemented, falling back to \"%s\".", 234220573Spjd curres->hr_replication == HAST_REPLICATION_MEMSYNC ? 235220573Spjd "memsync" : "async", "fullsync"); 236220573Spjd curres->hr_replication = HAST_REPLICATION_FULLSYNC; 237220573Spjd } 238219351Spjd if (curres->hr_checksum == -1) { 239219351Spjd /* 240219351Spjd * Checksum is not set at resource-level. 241219351Spjd * Use global or default setting. 242219351Spjd */ 243219351Spjd curres->hr_checksum = depth0_checksum; 244219351Spjd } 245219354Spjd if (curres->hr_compression == -1) { 246219354Spjd /* 247219354Spjd * Compression is not set at resource-level. 248219354Spjd * Use global or default setting. 249219354Spjd */ 250219354Spjd curres->hr_compression = depth0_compression; 251219354Spjd } 252207371Spjd if (curres->hr_timeout == -1) { 253207371Spjd /* 254207371Spjd * Timeout is not set at resource-level. 255207371Spjd * Use global or default setting. 256207371Spjd */ 257207371Spjd curres->hr_timeout = depth0_timeout; 258207371Spjd } 259211886Spjd if (curres->hr_exec[0] == '\0') { 260211886Spjd /* 261211886Spjd * Exec is not set at resource-level. 262211886Spjd * Use global or default setting. 263211886Spjd */ 264211886Spjd strlcpy(curres->hr_exec, depth0_exec, 265211886Spjd sizeof(curres->hr_exec)); 266211886Spjd } 267204076Spjd } 268204076Spjd 269210883Spjd return (lconfig); 270204076Spjd} 271204076Spjd 272204076Spjdvoid 273204076Spjdyy_config_free(struct hastd_config *config) 274204076Spjd{ 275204076Spjd struct hast_resource *res; 276204076Spjd 277204076Spjd while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) { 278204076Spjd TAILQ_REMOVE(&config->hc_resources, res, hr_next); 279204076Spjd free(res); 280204076Spjd } 281210883Spjd free(config); 282204076Spjd} 283204076Spjd%} 284204076Spjd 285219354Spjd%token CONTROL LISTEN PORT REPLICATION CHECKSUM COMPRESSION 286219818Spjd%token TIMEOUT EXEC EXTENTSIZE RESOURCE NAME LOCAL REMOTE SOURCE ON 287219354Spjd%token FULLSYNC MEMSYNC ASYNC NONE CRC32 SHA256 HOLE LZF 288204076Spjd%token NUM STR OB CB 289204076Spjd 290204076Spjd%type <num> replication_type 291219351Spjd%type <num> checksum_type 292219354Spjd%type <num> compression_type 293204076Spjd 294204076Spjd%union 295204076Spjd{ 296204076Spjd int num; 297204076Spjd char *str; 298204076Spjd} 299204076Spjd 300204076Spjd%token <num> NUM 301204076Spjd%token <str> STR 302204076Spjd 303204076Spjd%% 304204076Spjd 305204076Spjdstatements: 306204076Spjd | 307204076Spjd statements statement 308204076Spjd ; 309204076Spjd 310204076Spjdstatement: 311204076Spjd control_statement 312204076Spjd | 313204076Spjd listen_statement 314204076Spjd | 315204076Spjd replication_statement 316204076Spjd | 317219351Spjd checksum_statement 318219351Spjd | 319219354Spjd compression_statement 320219354Spjd | 321207371Spjd timeout_statement 322207371Spjd | 323211886Spjd exec_statement 324211886Spjd | 325204076Spjd node_statement 326204076Spjd | 327204076Spjd resource_statement 328204076Spjd ; 329204076Spjd 330204076Spjdcontrol_statement: CONTROL STR 331204076Spjd { 332204076Spjd switch (depth) { 333204076Spjd case 0: 334204076Spjd if (strlcpy(depth0_control, $2, 335204076Spjd sizeof(depth0_control)) >= 336204076Spjd sizeof(depth0_control)) { 337210883Spjd pjdlog_error("control argument is too long."); 338214274Spjd free($2); 339210883Spjd return (1); 340204076Spjd } 341204076Spjd break; 342204076Spjd case 1: 343211883Spjd if (!mynode) 344211883Spjd break; 345211883Spjd if (strlcpy(lconfig->hc_controladdr, $2, 346211883Spjd sizeof(lconfig->hc_controladdr)) >= 347211883Spjd sizeof(lconfig->hc_controladdr)) { 348211883Spjd pjdlog_error("control argument is too long."); 349214274Spjd free($2); 350211883Spjd return (1); 351204076Spjd } 352204076Spjd break; 353204076Spjd default: 354204076Spjd assert(!"control at wrong depth level"); 355204076Spjd } 356214274Spjd free($2); 357204076Spjd } 358204076Spjd ; 359204076Spjd 360204076Spjdlisten_statement: LISTEN STR 361204076Spjd { 362204076Spjd switch (depth) { 363204076Spjd case 0: 364204076Spjd if (strlcpy(depth0_listen, $2, 365204076Spjd sizeof(depth0_listen)) >= 366204076Spjd sizeof(depth0_listen)) { 367210883Spjd pjdlog_error("listen argument is too long."); 368214274Spjd free($2); 369210883Spjd return (1); 370204076Spjd } 371204076Spjd break; 372204076Spjd case 1: 373211883Spjd if (!mynode) 374211883Spjd break; 375211883Spjd if (strlcpy(lconfig->hc_listenaddr, $2, 376211883Spjd sizeof(lconfig->hc_listenaddr)) >= 377211883Spjd sizeof(lconfig->hc_listenaddr)) { 378211883Spjd pjdlog_error("listen argument is too long."); 379214274Spjd free($2); 380211883Spjd return (1); 381204076Spjd } 382204076Spjd break; 383204076Spjd default: 384204076Spjd assert(!"listen at wrong depth level"); 385204076Spjd } 386214274Spjd free($2); 387204076Spjd } 388204076Spjd ; 389204076Spjd 390204076Spjdreplication_statement: REPLICATION replication_type 391204076Spjd { 392204076Spjd switch (depth) { 393204076Spjd case 0: 394204076Spjd depth0_replication = $2; 395204076Spjd break; 396204076Spjd case 1: 397204076Spjd if (curres != NULL) 398204076Spjd curres->hr_replication = $2; 399204076Spjd break; 400204076Spjd default: 401204076Spjd assert(!"replication at wrong depth level"); 402204076Spjd } 403204076Spjd } 404204076Spjd ; 405204076Spjd 406204076Spjdreplication_type: 407204076Spjd FULLSYNC { $$ = HAST_REPLICATION_FULLSYNC; } 408204076Spjd | 409204076Spjd MEMSYNC { $$ = HAST_REPLICATION_MEMSYNC; } 410204076Spjd | 411204076Spjd ASYNC { $$ = HAST_REPLICATION_ASYNC; } 412204076Spjd ; 413204076Spjd 414219351Spjdchecksum_statement: CHECKSUM checksum_type 415219351Spjd { 416219351Spjd switch (depth) { 417219351Spjd case 0: 418219351Spjd depth0_checksum = $2; 419219351Spjd break; 420219351Spjd case 1: 421219351Spjd if (curres != NULL) 422219351Spjd curres->hr_checksum = $2; 423219351Spjd break; 424219351Spjd default: 425219351Spjd assert(!"checksum at wrong depth level"); 426219351Spjd } 427219351Spjd } 428219351Spjd ; 429219351Spjd 430219351Spjdchecksum_type: 431219351Spjd NONE { $$ = HAST_CHECKSUM_NONE; } 432219351Spjd | 433219351Spjd CRC32 { $$ = HAST_CHECKSUM_CRC32; } 434219351Spjd | 435219351Spjd SHA256 { $$ = HAST_CHECKSUM_SHA256; } 436219351Spjd ; 437219351Spjd 438219354Spjdcompression_statement: COMPRESSION compression_type 439219354Spjd { 440219354Spjd switch (depth) { 441219354Spjd case 0: 442219354Spjd depth0_compression = $2; 443219354Spjd break; 444219354Spjd case 1: 445219354Spjd if (curres != NULL) 446219354Spjd curres->hr_compression = $2; 447219354Spjd break; 448219354Spjd default: 449219354Spjd assert(!"compression at wrong depth level"); 450219354Spjd } 451219354Spjd } 452219354Spjd ; 453219354Spjd 454219354Spjdcompression_type: 455219354Spjd NONE { $$ = HAST_COMPRESSION_NONE; } 456219354Spjd | 457219354Spjd HOLE { $$ = HAST_COMPRESSION_HOLE; } 458219354Spjd | 459219354Spjd LZF { $$ = HAST_COMPRESSION_LZF; } 460219354Spjd ; 461219354Spjd 462207371Spjdtimeout_statement: TIMEOUT NUM 463207371Spjd { 464220889Spjd if ($2 <= 0) { 465220889Spjd pjdlog_error("Negative or zero timeout."); 466220889Spjd return (1); 467220889Spjd } 468207371Spjd switch (depth) { 469207371Spjd case 0: 470207371Spjd depth0_timeout = $2; 471207371Spjd break; 472207371Spjd case 1: 473207371Spjd if (curres != NULL) 474207371Spjd curres->hr_timeout = $2; 475207371Spjd break; 476207371Spjd default: 477207371Spjd assert(!"timeout at wrong depth level"); 478207371Spjd } 479207371Spjd } 480207371Spjd ; 481207371Spjd 482211886Spjdexec_statement: EXEC STR 483211886Spjd { 484211886Spjd switch (depth) { 485211886Spjd case 0: 486211886Spjd if (strlcpy(depth0_exec, $2, sizeof(depth0_exec)) >= 487211886Spjd sizeof(depth0_exec)) { 488211886Spjd pjdlog_error("Exec path is too long."); 489214274Spjd free($2); 490211886Spjd return (1); 491211886Spjd } 492211886Spjd break; 493211886Spjd case 1: 494211886Spjd if (curres == NULL) 495211886Spjd break; 496211886Spjd if (strlcpy(curres->hr_exec, $2, 497211886Spjd sizeof(curres->hr_exec)) >= 498211886Spjd sizeof(curres->hr_exec)) { 499211886Spjd pjdlog_error("Exec path is too long."); 500214274Spjd free($2); 501211886Spjd return (1); 502211886Spjd } 503211886Spjd break; 504211886Spjd default: 505211886Spjd assert(!"exec at wrong depth level"); 506211886Spjd } 507214274Spjd free($2); 508211886Spjd } 509211886Spjd ; 510211886Spjd 511204076Spjdnode_statement: ON node_start OB node_entries CB 512204076Spjd { 513204076Spjd mynode = false; 514204076Spjd } 515204076Spjd ; 516204076Spjd 517204076Spjdnode_start: STR 518204076Spjd { 519210883Spjd switch (isitme($1)) { 520210883Spjd case -1: 521214274Spjd free($1); 522210883Spjd return (1); 523210883Spjd case 0: 524210883Spjd break; 525210883Spjd case 1: 526204076Spjd mynode = true; 527210883Spjd break; 528210883Spjd default: 529210883Spjd assert(!"invalid isitme() return value"); 530210883Spjd } 531214274Spjd free($1); 532204076Spjd } 533204076Spjd ; 534204076Spjd 535204076Spjdnode_entries: 536204076Spjd | 537204076Spjd node_entries node_entry 538204076Spjd ; 539204076Spjd 540204076Spjdnode_entry: 541204076Spjd control_statement 542204076Spjd | 543204076Spjd listen_statement 544204076Spjd ; 545204076Spjd 546204076Spjdresource_statement: RESOURCE resource_start OB resource_entries CB 547204076Spjd { 548204076Spjd if (curres != NULL) { 549204076Spjd /* 550216721Spjd * There must be section for this node, at least with 551216721Spjd * remote address configuration. 552216721Spjd */ 553216721Spjd if (!hadmynode) { 554216721Spjd char *names; 555216721Spjd 556216721Spjd if (node_names(&names) != 0) 557216721Spjd return (1); 558216721Spjd pjdlog_error("No resource %s configuration for this node (acceptable node names: %s).", 559216721Spjd curres->hr_name, names); 560216721Spjd return (1); 561216721Spjd } 562216721Spjd 563216721Spjd /* 564204076Spjd * Let's see there are some resource-level settings 565204076Spjd * that we can use for node-level settings. 566204076Spjd */ 567204076Spjd if (curres->hr_provname[0] == '\0' && 568204076Spjd depth1_provname[0] != '\0') { 569204076Spjd /* 570204076Spjd * Provider name is not set at node-level, 571204076Spjd * but is set at resource-level, use it. 572204076Spjd */ 573204076Spjd strlcpy(curres->hr_provname, depth1_provname, 574204076Spjd sizeof(curres->hr_provname)); 575204076Spjd } 576204076Spjd if (curres->hr_localpath[0] == '\0' && 577204076Spjd depth1_localpath[0] != '\0') { 578204076Spjd /* 579204076Spjd * Path to local provider is not set at 580204076Spjd * node-level, but is set at resource-level, 581204076Spjd * use it. 582204076Spjd */ 583204076Spjd strlcpy(curres->hr_localpath, depth1_localpath, 584204076Spjd sizeof(curres->hr_localpath)); 585204076Spjd } 586204076Spjd 587204076Spjd /* 588204076Spjd * If provider name is not given, use resource name 589204076Spjd * as provider name. 590204076Spjd */ 591204076Spjd if (curres->hr_provname[0] == '\0') { 592204076Spjd strlcpy(curres->hr_provname, curres->hr_name, 593204076Spjd sizeof(curres->hr_provname)); 594204076Spjd } 595204076Spjd 596204076Spjd /* 597204076Spjd * Remote address has to be configured at this point. 598204076Spjd */ 599204076Spjd if (curres->hr_remoteaddr[0] == '\0') { 600210883Spjd pjdlog_error("Remote address not configured for resource %s.", 601204076Spjd curres->hr_name); 602210883Spjd return (1); 603204076Spjd } 604204076Spjd /* 605204076Spjd * Path to local provider has to be configured at this 606204076Spjd * point. 607204076Spjd */ 608204076Spjd if (curres->hr_localpath[0] == '\0') { 609210883Spjd pjdlog_error("Path to local component not configured for resource %s.", 610204076Spjd curres->hr_name); 611210883Spjd return (1); 612204076Spjd } 613204076Spjd 614204076Spjd /* Put it onto resource list. */ 615210883Spjd TAILQ_INSERT_TAIL(&lconfig->hc_resources, curres, hr_next); 616204076Spjd curres = NULL; 617204076Spjd } 618204076Spjd } 619204076Spjd ; 620204076Spjd 621204076Spjdresource_start: STR 622204076Spjd { 623216722Spjd /* Check if there is no duplicate entry. */ 624216722Spjd TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 625216722Spjd if (strcmp(curres->hr_name, $1) == 0) { 626216722Spjd pjdlog_error("Resource %s configured more than once.", 627216722Spjd curres->hr_name); 628216722Spjd free($1); 629216722Spjd return (1); 630216722Spjd } 631216722Spjd } 632216722Spjd 633204076Spjd /* 634204076Spjd * Clear those, so we can tell if they were set at 635204076Spjd * resource-level or not. 636204076Spjd */ 637204076Spjd depth1_provname[0] = '\0'; 638204076Spjd depth1_localpath[0] = '\0'; 639216721Spjd hadmynode = false; 640204076Spjd 641204076Spjd curres = calloc(1, sizeof(*curres)); 642204076Spjd if (curres == NULL) { 643210883Spjd pjdlog_error("Unable to allocate memory for resource."); 644214274Spjd free($1); 645210883Spjd return (1); 646204076Spjd } 647204076Spjd if (strlcpy(curres->hr_name, $1, 648204076Spjd sizeof(curres->hr_name)) >= 649204076Spjd sizeof(curres->hr_name)) { 650210883Spjd pjdlog_error("Resource name is too long."); 651214274Spjd free($1); 652210883Spjd return (1); 653204076Spjd } 654214274Spjd free($1); 655204076Spjd curres->hr_role = HAST_ROLE_INIT; 656204076Spjd curres->hr_previous_role = HAST_ROLE_INIT; 657204076Spjd curres->hr_replication = -1; 658219351Spjd curres->hr_checksum = -1; 659219354Spjd curres->hr_compression = -1; 660207371Spjd curres->hr_timeout = -1; 661211886Spjd curres->hr_exec[0] = '\0'; 662204076Spjd curres->hr_provname[0] = '\0'; 663204076Spjd curres->hr_localpath[0] = '\0'; 664204076Spjd curres->hr_localfd = -1; 665204076Spjd curres->hr_remoteaddr[0] = '\0'; 666219818Spjd curres->hr_sourceaddr[0] = '\0'; 667204076Spjd curres->hr_ggateunit = -1; 668204076Spjd } 669204076Spjd ; 670204076Spjd 671204076Spjdresource_entries: 672204076Spjd | 673204076Spjd resource_entries resource_entry 674204076Spjd ; 675204076Spjd 676204076Spjdresource_entry: 677204076Spjd replication_statement 678204076Spjd | 679219351Spjd checksum_statement 680219351Spjd | 681219354Spjd compression_statement 682219354Spjd | 683207371Spjd timeout_statement 684207371Spjd | 685211886Spjd exec_statement 686211886Spjd | 687204076Spjd name_statement 688204076Spjd | 689204076Spjd local_statement 690204076Spjd | 691204076Spjd resource_node_statement 692204076Spjd ; 693204076Spjd 694204076Spjdname_statement: NAME STR 695204076Spjd { 696204076Spjd switch (depth) { 697204076Spjd case 1: 698204076Spjd if (strlcpy(depth1_provname, $2, 699204076Spjd sizeof(depth1_provname)) >= 700204076Spjd sizeof(depth1_provname)) { 701210883Spjd pjdlog_error("name argument is too long."); 702214274Spjd free($2); 703210883Spjd return (1); 704204076Spjd } 705204076Spjd break; 706204076Spjd case 2: 707211883Spjd if (!mynode) 708211883Spjd break; 709211883Spjd assert(curres != NULL); 710211883Spjd if (strlcpy(curres->hr_provname, $2, 711211883Spjd sizeof(curres->hr_provname)) >= 712211883Spjd sizeof(curres->hr_provname)) { 713211883Spjd pjdlog_error("name argument is too long."); 714214274Spjd free($2); 715211883Spjd return (1); 716204076Spjd } 717204076Spjd break; 718204076Spjd default: 719204076Spjd assert(!"name at wrong depth level"); 720204076Spjd } 721214274Spjd free($2); 722204076Spjd } 723204076Spjd ; 724204076Spjd 725204076Spjdlocal_statement: LOCAL STR 726204076Spjd { 727204076Spjd switch (depth) { 728204076Spjd case 1: 729204076Spjd if (strlcpy(depth1_localpath, $2, 730204076Spjd sizeof(depth1_localpath)) >= 731204076Spjd sizeof(depth1_localpath)) { 732210883Spjd pjdlog_error("local argument is too long."); 733214274Spjd free($2); 734210883Spjd return (1); 735204076Spjd } 736204076Spjd break; 737204076Spjd case 2: 738211883Spjd if (!mynode) 739211883Spjd break; 740211883Spjd assert(curres != NULL); 741211883Spjd if (strlcpy(curres->hr_localpath, $2, 742211883Spjd sizeof(curres->hr_localpath)) >= 743211883Spjd sizeof(curres->hr_localpath)) { 744211883Spjd pjdlog_error("local argument is too long."); 745214274Spjd free($2); 746211883Spjd return (1); 747204076Spjd } 748204076Spjd break; 749204076Spjd default: 750204076Spjd assert(!"local at wrong depth level"); 751204076Spjd } 752214274Spjd free($2); 753204076Spjd } 754204076Spjd ; 755204076Spjd 756204076Spjdresource_node_statement:ON resource_node_start OB resource_node_entries CB 757204076Spjd { 758204076Spjd mynode = false; 759204076Spjd } 760204076Spjd ; 761204076Spjd 762204076Spjdresource_node_start: STR 763204076Spjd { 764210883Spjd if (curres != NULL) { 765210883Spjd switch (isitme($1)) { 766210883Spjd case -1: 767214274Spjd free($1); 768210883Spjd return (1); 769210883Spjd case 0: 770210883Spjd break; 771210883Spjd case 1: 772216721Spjd mynode = hadmynode = true; 773210883Spjd break; 774210883Spjd default: 775210883Spjd assert(!"invalid isitme() return value"); 776210883Spjd } 777210883Spjd } 778214274Spjd free($1); 779204076Spjd } 780204076Spjd ; 781204076Spjd 782204076Spjdresource_node_entries: 783204076Spjd | 784204076Spjd resource_node_entries resource_node_entry 785204076Spjd ; 786204076Spjd 787204076Spjdresource_node_entry: 788204076Spjd name_statement 789204076Spjd | 790204076Spjd local_statement 791204076Spjd | 792204076Spjd remote_statement 793219818Spjd | 794219818Spjd source_statement 795204076Spjd ; 796204076Spjd 797204076Spjdremote_statement: REMOTE STR 798204076Spjd { 799204076Spjd assert(depth == 2); 800204076Spjd if (mynode) { 801204076Spjd assert(curres != NULL); 802204076Spjd if (strlcpy(curres->hr_remoteaddr, $2, 803204076Spjd sizeof(curres->hr_remoteaddr)) >= 804204076Spjd sizeof(curres->hr_remoteaddr)) { 805210883Spjd pjdlog_error("remote argument is too long."); 806214274Spjd free($2); 807210883Spjd return (1); 808204076Spjd } 809204076Spjd } 810214274Spjd free($2); 811204076Spjd } 812204076Spjd ; 813219818Spjd 814219818Spjdsource_statement: SOURCE STR 815219818Spjd { 816219818Spjd assert(depth == 2); 817219818Spjd if (mynode) { 818219818Spjd assert(curres != NULL); 819219818Spjd if (strlcpy(curres->hr_sourceaddr, $2, 820219818Spjd sizeof(curres->hr_sourceaddr)) >= 821219818Spjd sizeof(curres->hr_sourceaddr)) { 822219818Spjd pjdlog_error("source argument is too long."); 823219818Spjd free($2); 824219818Spjd return (1); 825219818Spjd } 826219818Spjd } 827219818Spjd free($2); 828219818Spjd } 829219818Spjd ; 830