parse.y (230976) | parse.y (235789) |
---|---|
1%{ 2/*- 3 * Copyright (c) 2009-2010 The FreeBSD Foundation 4 * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> 5 * All rights reserved. 6 * 7 * This software was developed by Pawel Jakub Dawidek under sponsorship from 8 * the FreeBSD Foundation. --- 14 unchanged lines hidden (view full) --- 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * | 1%{ 2/*- 3 * Copyright (c) 2009-2010 The FreeBSD Foundation 4 * Copyright (c) 2011 Pawel Jakub Dawidek <pawel@dawidek.net> 5 * All rights reserved. 6 * 7 * This software was developed by Pawel Jakub Dawidek under sponsorship from 8 * the FreeBSD Foundation. --- 14 unchanged lines hidden (view full) --- 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * |
31 * $FreeBSD: head/sbin/hastd/parse.y 230976 2012-02-04 07:59:12Z pjd $ | 31 * $FreeBSD: head/sbin/hastd/parse.y 235789 2012-05-22 16:33:10Z bapt $ |
32 */ 33 34#include <sys/param.h> /* MAXHOSTNAMELEN */ 35#include <sys/queue.h> 36#include <sys/socket.h> 37#include <sys/sysctl.h> 38 39#include <arpa/inet.h> --- 32 unchanged lines hidden (view full) --- 72static int depth0_metaflush; 73 74static char depth1_provname[PATH_MAX]; 75static char depth1_localpath[PATH_MAX]; 76static int depth1_metaflush; 77 78extern void yyrestart(FILE *); 79 | 32 */ 33 34#include <sys/param.h> /* MAXHOSTNAMELEN */ 35#include <sys/queue.h> 36#include <sys/socket.h> 37#include <sys/sysctl.h> 38 39#include <arpa/inet.h> --- 32 unchanged lines hidden (view full) --- 72static int depth0_metaflush; 73 74static char depth1_provname[PATH_MAX]; 75static char depth1_localpath[PATH_MAX]; 76static int depth1_metaflush; 77 78extern void yyrestart(FILE *); 79 |
80static int 81isitme(const char *name) 82{ 83 char buf[MAXHOSTNAMELEN]; 84 char *pos; 85 size_t bufsize; 86 87 /* 88 * First check if the given name matches our full hostname. 89 */ 90 if (gethostname(buf, sizeof(buf)) < 0) { 91 pjdlog_errno(LOG_ERR, "gethostname() failed"); 92 return (-1); 93 } 94 if (strcmp(buf, name) == 0) 95 return (1); 96 97 /* 98 * Now check if it matches first part of the host name. 99 */ 100 pos = strchr(buf, '.'); 101 if (pos != NULL && (size_t)(pos - buf) == strlen(name) && 102 strncmp(buf, name, pos - buf) == 0) { 103 return (1); 104 } 105 106 /* 107 * At the end check if name is equal to our host's UUID. 108 */ 109 bufsize = sizeof(buf); 110 if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 111 pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 112 return (-1); 113 } 114 if (strcasecmp(buf, name) == 0) 115 return (1); 116 117 /* 118 * Looks like this isn't about us. 119 */ 120 return (0); 121} 122 123static bool 124family_supported(int family) 125{ 126 int sock; 127 128 sock = socket(family, SOCK_STREAM, 0); 129 if (sock == -1 && errno == EPROTONOSUPPORT) 130 return (false); 131 if (sock >= 0) 132 (void)close(sock); 133 return (true); 134} 135 136static int 137node_names(char **namesp) 138{ 139 static char names[MAXHOSTNAMELEN * 3]; 140 char buf[MAXHOSTNAMELEN]; 141 char *pos; 142 size_t bufsize; 143 144 if (gethostname(buf, sizeof(buf)) < 0) { 145 pjdlog_errno(LOG_ERR, "gethostname() failed"); 146 return (-1); 147 } 148 149 /* First component of the host name. */ 150 pos = strchr(buf, '.'); 151 if (pos != NULL && pos != buf) { 152 (void)strlcpy(names, buf, MIN((size_t)(pos - buf + 1), 153 sizeof(names))); 154 (void)strlcat(names, ", ", sizeof(names)); 155 } 156 157 /* Full host name. */ 158 (void)strlcat(names, buf, sizeof(names)); 159 (void)strlcat(names, ", ", sizeof(names)); 160 161 /* Host UUID. */ 162 bufsize = sizeof(buf); 163 if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 164 pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 165 return (-1); 166 } 167 (void)strlcat(names, buf, sizeof(names)); 168 169 *namesp = names; 170 171 return (0); 172} 173 174void 175yyerror(const char *str) 176{ 177 178 pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", 179 lineno, yytext, str); 180} 181 182struct hastd_config * 183yy_config_parse(const char *config, bool exitonerror) 184{ 185 int ret; 186 187 curres = NULL; 188 mynode = false; 189 depth = 0; 190 lineno = 0; 191 192 depth0_timeout = HAST_TIMEOUT; 193 depth0_replication = HAST_REPLICATION_FULLSYNC; 194 depth0_checksum = HAST_CHECKSUM_NONE; 195 depth0_compression = HAST_COMPRESSION_HOLE; 196 strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control)); 197 strlcpy(depth0_pidfile, HASTD_PIDFILE, sizeof(depth0_pidfile)); 198 TAILQ_INIT(&depth0_listen); 199 strlcpy(depth0_listen_tcp4, HASTD_LISTEN_TCP4, 200 sizeof(depth0_listen_tcp4)); 201 strlcpy(depth0_listen_tcp6, HASTD_LISTEN_TCP6, 202 sizeof(depth0_listen_tcp6)); 203 depth0_exec[0] = '\0'; 204 depth0_metaflush = 1; 205 206 lconfig = calloc(1, sizeof(*lconfig)); 207 if (lconfig == NULL) { 208 pjdlog_error("Unable to allocate memory for configuration."); 209 if (exitonerror) 210 exit(EX_TEMPFAIL); 211 return (NULL); 212 } 213 214 TAILQ_INIT(&lconfig->hc_listen); 215 TAILQ_INIT(&lconfig->hc_resources); 216 217 yyin = fopen(config, "r"); 218 if (yyin == NULL) { 219 pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", 220 config); 221 yy_config_free(lconfig); 222 if (exitonerror) 223 exit(EX_OSFILE); 224 return (NULL); 225 } 226 yyrestart(yyin); 227 ret = yyparse(); 228 fclose(yyin); 229 if (ret != 0) { 230 yy_config_free(lconfig); 231 if (exitonerror) 232 exit(EX_CONFIG); 233 return (NULL); 234 } 235 236 /* 237 * Let's see if everything is set up. 238 */ 239 if (lconfig->hc_controladdr[0] == '\0') { 240 strlcpy(lconfig->hc_controladdr, depth0_control, 241 sizeof(lconfig->hc_controladdr)); 242 } 243 if (lconfig->hc_pidfile[0] == '\0') { 244 strlcpy(lconfig->hc_pidfile, depth0_pidfile, 245 sizeof(lconfig->hc_pidfile)); 246 } 247 if (!TAILQ_EMPTY(&depth0_listen)) 248 TAILQ_CONCAT(&lconfig->hc_listen, &depth0_listen, hl_next); 249 if (TAILQ_EMPTY(&lconfig->hc_listen)) { 250 struct hastd_listen *lst; 251 252 if (family_supported(AF_INET)) { 253 lst = calloc(1, sizeof(*lst)); 254 if (lst == NULL) { 255 pjdlog_error("Unable to allocate memory for listen address."); 256 yy_config_free(lconfig); 257 if (exitonerror) 258 exit(EX_TEMPFAIL); 259 return (NULL); 260 } 261 (void)strlcpy(lst->hl_addr, depth0_listen_tcp4, 262 sizeof(lst->hl_addr)); 263 TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 264 } else { 265 pjdlog_debug(1, 266 "No IPv4 support in the kernel, not listening on IPv4 address."); 267 } 268 if (family_supported(AF_INET6)) { 269 lst = calloc(1, sizeof(*lst)); 270 if (lst == NULL) { 271 pjdlog_error("Unable to allocate memory for listen address."); 272 yy_config_free(lconfig); 273 if (exitonerror) 274 exit(EX_TEMPFAIL); 275 return (NULL); 276 } 277 (void)strlcpy(lst->hl_addr, depth0_listen_tcp6, 278 sizeof(lst->hl_addr)); 279 TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 280 } else { 281 pjdlog_debug(1, 282 "No IPv6 support in the kernel, not listening on IPv6 address."); 283 } 284 if (TAILQ_EMPTY(&lconfig->hc_listen)) { 285 pjdlog_error("No address to listen on."); 286 yy_config_free(lconfig); 287 if (exitonerror) 288 exit(EX_TEMPFAIL); 289 return (NULL); 290 } 291 } 292 TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 293 PJDLOG_ASSERT(curres->hr_provname[0] != '\0'); 294 PJDLOG_ASSERT(curres->hr_localpath[0] != '\0'); 295 PJDLOG_ASSERT(curres->hr_remoteaddr[0] != '\0'); 296 297 if (curres->hr_replication == -1) { 298 /* 299 * Replication is not set at resource-level. 300 * Use global or default setting. 301 */ 302 curres->hr_replication = depth0_replication; 303 } 304 if (curres->hr_replication == HAST_REPLICATION_MEMSYNC) { 305 pjdlog_warning("Replication mode \"%s\" is not implemented, falling back to \"%s\".", 306 "memsync", "fullsync"); 307 curres->hr_replication = HAST_REPLICATION_FULLSYNC; 308 } 309 if (curres->hr_checksum == -1) { 310 /* 311 * Checksum is not set at resource-level. 312 * Use global or default setting. 313 */ 314 curres->hr_checksum = depth0_checksum; 315 } 316 if (curres->hr_compression == -1) { 317 /* 318 * Compression is not set at resource-level. 319 * Use global or default setting. 320 */ 321 curres->hr_compression = depth0_compression; 322 } 323 if (curres->hr_timeout == -1) { 324 /* 325 * Timeout is not set at resource-level. 326 * Use global or default setting. 327 */ 328 curres->hr_timeout = depth0_timeout; 329 } 330 if (curres->hr_exec[0] == '\0') { 331 /* 332 * Exec is not set at resource-level. 333 * Use global or default setting. 334 */ 335 strlcpy(curres->hr_exec, depth0_exec, 336 sizeof(curres->hr_exec)); 337 } 338 if (curres->hr_metaflush == -1) { 339 /* 340 * Metaflush is not set at resource-level. 341 * Use global or default setting. 342 */ 343 curres->hr_metaflush = depth0_metaflush; 344 } 345 } 346 347 return (lconfig); 348} 349 350void 351yy_config_free(struct hastd_config *config) 352{ 353 struct hastd_listen *lst; 354 struct hast_resource *res; 355 356 while ((lst = TAILQ_FIRST(&depth0_listen)) != NULL) { 357 TAILQ_REMOVE(&depth0_listen, lst, hl_next); 358 free(lst); 359 } 360 while ((lst = TAILQ_FIRST(&config->hc_listen)) != NULL) { 361 TAILQ_REMOVE(&config->hc_listen, lst, hl_next); 362 free(lst); 363 } 364 while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) { 365 TAILQ_REMOVE(&config->hc_resources, res, hr_next); 366 free(res); 367 } 368 free(config); 369} | 80static int isitme(const char *name); 81static bool family_supported(int family); 82static int node_names(char **namesp); |
370%} 371 372%token CONTROL PIDFILE LISTEN REPLICATION CHECKSUM COMPRESSION METAFLUSH 373%token TIMEOUT EXEC RESOURCE NAME LOCAL REMOTE SOURCE ON OFF 374%token FULLSYNC MEMSYNC ASYNC NONE CRC32 SHA256 HOLE LZF 375%token NUM STR OB CB 376 377%type <str> remote_str --- 621 unchanged lines hidden (view full) --- 999 pjdlog_error("source argument is too long."); 1000 free($2); 1001 return (1); 1002 } 1003 } 1004 free($2); 1005 } 1006 ; | 83%} 84 85%token CONTROL PIDFILE LISTEN REPLICATION CHECKSUM COMPRESSION METAFLUSH 86%token TIMEOUT EXEC RESOURCE NAME LOCAL REMOTE SOURCE ON OFF 87%token FULLSYNC MEMSYNC ASYNC NONE CRC32 SHA256 HOLE LZF 88%token NUM STR OB CB 89 90%type <str> remote_str --- 621 unchanged lines hidden (view full) --- 712 pjdlog_error("source argument is too long."); 713 free($2); 714 return (1); 715 } 716 } 717 free($2); 718 } 719 ; |
720 721%% 722 723static int 724isitme(const char *name) 725{ 726 char buf[MAXHOSTNAMELEN]; 727 char *pos; 728 size_t bufsize; 729 730 /* 731 * First check if the given name matches our full hostname. 732 */ 733 if (gethostname(buf, sizeof(buf)) < 0) { 734 pjdlog_errno(LOG_ERR, "gethostname() failed"); 735 return (-1); 736 } 737 if (strcmp(buf, name) == 0) 738 return (1); 739 740 /* 741 * Now check if it matches first part of the host name. 742 */ 743 pos = strchr(buf, '.'); 744 if (pos != NULL && (size_t)(pos - buf) == strlen(name) && 745 strncmp(buf, name, pos - buf) == 0) { 746 return (1); 747 } 748 749 /* 750 * At the end check if name is equal to our host's UUID. 751 */ 752 bufsize = sizeof(buf); 753 if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 754 pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 755 return (-1); 756 } 757 if (strcasecmp(buf, name) == 0) 758 return (1); 759 760 /* 761 * Looks like this isn't about us. 762 */ 763 return (0); 764} 765 766static bool 767family_supported(int family) 768{ 769 int sock; 770 771 sock = socket(family, SOCK_STREAM, 0); 772 if (sock == -1 && errno == EPROTONOSUPPORT) 773 return (false); 774 if (sock >= 0) 775 (void)close(sock); 776 return (true); 777} 778 779static int 780node_names(char **namesp) 781{ 782 static char names[MAXHOSTNAMELEN * 3]; 783 char buf[MAXHOSTNAMELEN]; 784 char *pos; 785 size_t bufsize; 786 787 if (gethostname(buf, sizeof(buf)) < 0) { 788 pjdlog_errno(LOG_ERR, "gethostname() failed"); 789 return (-1); 790 } 791 792 /* First component of the host name. */ 793 pos = strchr(buf, '.'); 794 if (pos != NULL && pos != buf) { 795 (void)strlcpy(names, buf, MIN((size_t)(pos - buf + 1), 796 sizeof(names))); 797 (void)strlcat(names, ", ", sizeof(names)); 798 } 799 800 /* Full host name. */ 801 (void)strlcat(names, buf, sizeof(names)); 802 (void)strlcat(names, ", ", sizeof(names)); 803 804 /* Host UUID. */ 805 bufsize = sizeof(buf); 806 if (sysctlbyname("kern.hostuuid", buf, &bufsize, NULL, 0) < 0) { 807 pjdlog_errno(LOG_ERR, "sysctlbyname(kern.hostuuid) failed"); 808 return (-1); 809 } 810 (void)strlcat(names, buf, sizeof(names)); 811 812 *namesp = names; 813 814 return (0); 815} 816 817void 818yyerror(const char *str) 819{ 820 821 pjdlog_error("Unable to parse configuration file at line %d near '%s': %s", 822 lineno, yytext, str); 823} 824 825struct hastd_config * 826yy_config_parse(const char *config, bool exitonerror) 827{ 828 int ret; 829 830 curres = NULL; 831 mynode = false; 832 depth = 0; 833 lineno = 0; 834 835 depth0_timeout = HAST_TIMEOUT; 836 depth0_replication = HAST_REPLICATION_FULLSYNC; 837 depth0_checksum = HAST_CHECKSUM_NONE; 838 depth0_compression = HAST_COMPRESSION_HOLE; 839 strlcpy(depth0_control, HAST_CONTROL, sizeof(depth0_control)); 840 strlcpy(depth0_pidfile, HASTD_PIDFILE, sizeof(depth0_pidfile)); 841 TAILQ_INIT(&depth0_listen); 842 strlcpy(depth0_listen_tcp4, HASTD_LISTEN_TCP4, 843 sizeof(depth0_listen_tcp4)); 844 strlcpy(depth0_listen_tcp6, HASTD_LISTEN_TCP6, 845 sizeof(depth0_listen_tcp6)); 846 depth0_exec[0] = '\0'; 847 depth0_metaflush = 1; 848 849 lconfig = calloc(1, sizeof(*lconfig)); 850 if (lconfig == NULL) { 851 pjdlog_error("Unable to allocate memory for configuration."); 852 if (exitonerror) 853 exit(EX_TEMPFAIL); 854 return (NULL); 855 } 856 857 TAILQ_INIT(&lconfig->hc_listen); 858 TAILQ_INIT(&lconfig->hc_resources); 859 860 yyin = fopen(config, "r"); 861 if (yyin == NULL) { 862 pjdlog_errno(LOG_ERR, "Unable to open configuration file %s", 863 config); 864 yy_config_free(lconfig); 865 if (exitonerror) 866 exit(EX_OSFILE); 867 return (NULL); 868 } 869 yyrestart(yyin); 870 ret = yyparse(); 871 fclose(yyin); 872 if (ret != 0) { 873 yy_config_free(lconfig); 874 if (exitonerror) 875 exit(EX_CONFIG); 876 return (NULL); 877 } 878 879 /* 880 * Let's see if everything is set up. 881 */ 882 if (lconfig->hc_controladdr[0] == '\0') { 883 strlcpy(lconfig->hc_controladdr, depth0_control, 884 sizeof(lconfig->hc_controladdr)); 885 } 886 if (lconfig->hc_pidfile[0] == '\0') { 887 strlcpy(lconfig->hc_pidfile, depth0_pidfile, 888 sizeof(lconfig->hc_pidfile)); 889 } 890 if (!TAILQ_EMPTY(&depth0_listen)) 891 TAILQ_CONCAT(&lconfig->hc_listen, &depth0_listen, hl_next); 892 if (TAILQ_EMPTY(&lconfig->hc_listen)) { 893 struct hastd_listen *lst; 894 895 if (family_supported(AF_INET)) { 896 lst = calloc(1, sizeof(*lst)); 897 if (lst == NULL) { 898 pjdlog_error("Unable to allocate memory for listen address."); 899 yy_config_free(lconfig); 900 if (exitonerror) 901 exit(EX_TEMPFAIL); 902 return (NULL); 903 } 904 (void)strlcpy(lst->hl_addr, depth0_listen_tcp4, 905 sizeof(lst->hl_addr)); 906 TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 907 } else { 908 pjdlog_debug(1, 909 "No IPv4 support in the kernel, not listening on IPv4 address."); 910 } 911 if (family_supported(AF_INET6)) { 912 lst = calloc(1, sizeof(*lst)); 913 if (lst == NULL) { 914 pjdlog_error("Unable to allocate memory for listen address."); 915 yy_config_free(lconfig); 916 if (exitonerror) 917 exit(EX_TEMPFAIL); 918 return (NULL); 919 } 920 (void)strlcpy(lst->hl_addr, depth0_listen_tcp6, 921 sizeof(lst->hl_addr)); 922 TAILQ_INSERT_TAIL(&lconfig->hc_listen, lst, hl_next); 923 } else { 924 pjdlog_debug(1, 925 "No IPv6 support in the kernel, not listening on IPv6 address."); 926 } 927 if (TAILQ_EMPTY(&lconfig->hc_listen)) { 928 pjdlog_error("No address to listen on."); 929 yy_config_free(lconfig); 930 if (exitonerror) 931 exit(EX_TEMPFAIL); 932 return (NULL); 933 } 934 } 935 TAILQ_FOREACH(curres, &lconfig->hc_resources, hr_next) { 936 PJDLOG_ASSERT(curres->hr_provname[0] != '\0'); 937 PJDLOG_ASSERT(curres->hr_localpath[0] != '\0'); 938 PJDLOG_ASSERT(curres->hr_remoteaddr[0] != '\0'); 939 940 if (curres->hr_replication == -1) { 941 /* 942 * Replication is not set at resource-level. 943 * Use global or default setting. 944 */ 945 curres->hr_replication = depth0_replication; 946 } 947 if (curres->hr_replication == HAST_REPLICATION_MEMSYNC) { 948 pjdlog_warning("Replication mode \"%s\" is not implemented, falling back to \"%s\".", 949 "memsync", "fullsync"); 950 curres->hr_replication = HAST_REPLICATION_FULLSYNC; 951 } 952 if (curres->hr_checksum == -1) { 953 /* 954 * Checksum is not set at resource-level. 955 * Use global or default setting. 956 */ 957 curres->hr_checksum = depth0_checksum; 958 } 959 if (curres->hr_compression == -1) { 960 /* 961 * Compression is not set at resource-level. 962 * Use global or default setting. 963 */ 964 curres->hr_compression = depth0_compression; 965 } 966 if (curres->hr_timeout == -1) { 967 /* 968 * Timeout is not set at resource-level. 969 * Use global or default setting. 970 */ 971 curres->hr_timeout = depth0_timeout; 972 } 973 if (curres->hr_exec[0] == '\0') { 974 /* 975 * Exec is not set at resource-level. 976 * Use global or default setting. 977 */ 978 strlcpy(curres->hr_exec, depth0_exec, 979 sizeof(curres->hr_exec)); 980 } 981 if (curres->hr_metaflush == -1) { 982 /* 983 * Metaflush is not set at resource-level. 984 * Use global or default setting. 985 */ 986 curres->hr_metaflush = depth0_metaflush; 987 } 988 } 989 990 return (lconfig); 991} 992 993void 994yy_config_free(struct hastd_config *config) 995{ 996 struct hastd_listen *lst; 997 struct hast_resource *res; 998 999 while ((lst = TAILQ_FIRST(&depth0_listen)) != NULL) { 1000 TAILQ_REMOVE(&depth0_listen, lst, hl_next); 1001 free(lst); 1002 } 1003 while ((lst = TAILQ_FIRST(&config->hc_listen)) != NULL) { 1004 TAILQ_REMOVE(&config->hc_listen, lst, hl_next); 1005 free(lst); 1006 } 1007 while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) { 1008 TAILQ_REMOVE(&config->hc_resources, res, hr_next); 1009 free(res); 1010 } 1011 free(config); 1012} |
|