1 #include "first.h" 2 3 #include "array.h" 4 #include "configfile.h" 5 6 #include <string.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 #ifdef HAVE_PCRE_H 11 #include <pcre.h> 12 #ifndef PCRE_STUDY_JIT_COMPILE 13 #define PCRE_STUDY_JIT_COMPILE 0 14 #define pcre_free_study(x) pcre_free(x) 15 #endif 16 #endif 17 18 __attribute_cold__ 19 static data_unset *data_config_copy(const data_unset *s) { 20 data_config *src = (data_config *)s; 21 data_config *ds = data_config_init(); 22 23 ds->comp = src->comp; 24 if (!buffer_is_empty(&src->key)) { 25 buffer_copy_buffer(&ds->key, &src->key); 26 ds->comp_key = ds->key.ptr + (src->comp_key - src->key.ptr); 27 } 28 buffer_copy_buffer(&ds->comp_tag, &src->comp_tag); 29 array_copy_array(ds->value, src->value); 30 return (data_unset *)ds; 31 } 32 33 __attribute_cold__ 34 static void data_config_free(data_unset *d) { 35 data_config *ds = (data_config *)d; 36 37 free(ds->key.ptr); 38 free(ds->comp_tag.ptr); 39 40 array_free(ds->value); 41 vector_config_weak_clear(&ds->children); 42 43 free(ds->string.ptr); 44 #ifdef HAVE_PCRE_H 45 if (ds->regex) pcre_free(ds->regex); 46 if (ds->regex_study) pcre_free_study(ds->regex_study); 47 #endif 48 49 free(d); 50 } 51 52 __attribute_cold__ 53 static int data_config_insert_dup(data_unset *dst, data_unset *src) { 54 UNUSED(dst); 55 56 src->fn->free(src); 57 58 return 0; 59 } 60 61 __attribute_cold__ 62 static void data_config_print(const data_unset *d, int depth) { 63 data_config *ds = (data_config *)d; 64 array *a = (array *)ds->value; 65 size_t i; 66 size_t maxlen; 67 68 if (0 == ds->context_ndx) { 69 fprintf(stdout, "config {\n"); 70 } 71 else { 72 if (ds->cond != CONFIG_COND_ELSE) { 73 fprintf(stdout, "%s {\n", ds->comp_key); 74 } else { 75 fprintf(stdout, "{\n"); 76 } 77 array_print_indent(depth + 1); 78 fprintf(stdout, "# block %d\n", ds->context_ndx); 79 } 80 depth ++; 81 82 maxlen = array_get_max_key_length(a); 83 for (i = 0; i < a->used; i ++) { 84 data_unset *du = a->data[i]; 85 size_t len = buffer_string_length(&du->key); 86 size_t j; 87 88 array_print_indent(depth); 89 fprintf(stdout, "%s", du->key.ptr); 90 for (j = maxlen - len; j > 0; j --) { 91 fprintf(stdout, " "); 92 } 93 fprintf(stdout, " = "); 94 du->fn->print(du, depth); 95 fprintf(stdout, "\n"); 96 } 97 98 fprintf(stdout, "\n"); 99 for (i = 0; i < ds->children.used; i ++) { 100 data_config *dc = ds->children.data[i]; 101 102 /* only the 1st block of chaining */ 103 if (NULL == dc->prev) { 104 fprintf(stdout, "\n"); 105 array_print_indent(depth); 106 dc->fn->print((data_unset *) dc, depth); 107 fprintf(stdout, "\n"); 108 } 109 } 110 111 depth --; 112 array_print_indent(depth); 113 fprintf(stdout, "}"); 114 if (0 != ds->context_ndx) { 115 if (ds->cond != CONFIG_COND_ELSE) { 116 fprintf(stdout, " # end of %s", ds->comp_key); 117 } else { 118 fprintf(stdout, " # end of else"); 119 } 120 } 121 122 if (ds->next) { 123 fprintf(stdout, "\n"); 124 array_print_indent(depth); 125 fprintf(stdout, "else "); 126 ds->next->fn->print((data_unset *)ds->next, depth); 127 } 128 } 129 130 data_config *data_config_init(void) { 131 static const struct data_methods fn = { 132 data_config_copy, 133 data_config_free, 134 data_config_insert_dup, 135 data_config_print, 136 }; 137 data_config *ds; 138 139 ds = calloc(1, sizeof(*ds)); 140 force_assert(ds); 141 142 ds->comp_key = ""; 143 ds->value = array_init(4); 144 vector_config_weak_init(&ds->children); 145 146 ds->type = TYPE_CONFIG; 147 ds->fn = &fn; 148 149 return ds; 150 } 151 152 #include "log.h" 153 154 int data_config_pcre_compile(data_config * const dc, const int pcre_jit, log_error_st * const errh) { 155 #ifdef HAVE_PCRE_H 156 const char *errptr; 157 int erroff, captures; 158 159 dc->regex = pcre_compile(dc->string.ptr, 0, &errptr, &erroff, NULL); 160 if (NULL == dc->regex) { 161 log_error(errh, __FILE__, __LINE__, 162 "parsing regex failed: %s -> %s at offset %d\n", 163 dc->string.ptr, errptr, erroff); 164 return 0; 165 } 166 167 const int study_options = pcre_jit ? PCRE_STUDY_JIT_COMPILE : 0; 168 dc->regex_study = pcre_study(dc->regex, study_options, &errptr); 169 if (NULL == dc->regex_study && errptr != NULL) { 170 log_error(errh, __FILE__, __LINE__, 171 "studying regex failed: %s -> %s\n", 172 dc->string.ptr, errptr); 173 return 0; 174 } 175 176 erroff = pcre_fullinfo(dc->regex, dc->regex_study, PCRE_INFO_CAPTURECOUNT, 177 &captures); 178 if (0 != erroff) { 179 log_error(errh, __FILE__, __LINE__, 180 "getting capture count for regex failed: %s\n", 181 dc->string.ptr); 182 return 0; 183 } 184 else if (captures > 9) { 185 log_error(errh, __FILE__, __LINE__, 186 "Too many captures in regex, use (?:...) instead of (...): %s\n", 187 dc->string.ptr); 188 return 0; 189 } 190 return 1; 191 #else 192 UNUSED(pcre_jit); 193 log_error(errh, __FILE__, __LINE__, 194 "can't handle '%s' as you compiled without pcre support. \n" 195 "(perhaps just a missing pcre-devel package ?) \n", 196 dc->comp_key); 197 return 0; 198 #endif 199 } 200