| 44 | | |
|---|
| 45 | | static noit_hash_table interpolation_operators = NOIT_HASH_EMPTY; |
|---|
| 46 | | |
|---|
| 47 | | static int |
|---|
| 48 | | interpolate_oper_copy(char *buff, int len, const char *replacement) { |
|---|
| 49 | | strlcpy(buff, replacement, len); |
|---|
| 50 | | return strlen(buff); |
|---|
| 51 | | } |
|---|
| 52 | | static int |
|---|
| 53 | | interpolate_oper_ccns(char *buff, int len, const char *replacement) { |
|---|
| 54 | | char *start; |
|---|
| 55 | | start = strstr(replacement, "::"); |
|---|
| 56 | | return interpolate_oper_copy(buff, len, start ? (start + 2) : replacement); |
|---|
| 57 | | } |
|---|
| 58 | | |
|---|
| 59 | | int |
|---|
| 60 | | noit_check_interpolate_register_oper_fn(const char *name, |
|---|
| 61 | | intperpolate_oper_fn f) { |
|---|
| 62 | | noit_hash_replace(&interpolation_operators, |
|---|
| 63 | | strdup(name), strlen(name), |
|---|
| 64 | | (void *)f, |
|---|
| 65 | | free, NULL); |
|---|
| 66 | | return 0; |
|---|
| 67 | | } |
|---|
| 68 | | |
|---|
| 69 | | int |
|---|
| 70 | | noit_check_interpolate(char *buff, int len, const char *fmt, |
|---|
| 71 | | noit_hash_table *attrs, |
|---|
| 72 | | noit_hash_table *config) { |
|---|
| 73 | | char *copy = NULL; |
|---|
| 74 | | char closer; |
|---|
| 75 | | const char *fmte, *key; |
|---|
| 76 | | int replaced_something = 1; |
|---|
| 77 | | int iterations = 3; |
|---|
| 78 | | |
|---|
| 79 | | while(replaced_something && iterations > 0) { |
|---|
| 80 | | char *cp = buff, * const end = buff + len; |
|---|
| 81 | | iterations--; |
|---|
| 82 | | replaced_something = 0; |
|---|
| 83 | | while(*fmt && cp < end) { |
|---|
| 84 | | switch(*fmt) { |
|---|
| 85 | | case '%': |
|---|
| 86 | | if(fmt[1] == '{' || fmt[1] == '[') { |
|---|
| 87 | | closer = (fmt[1] == '{') ? '}' : ']'; |
|---|
| 88 | | fmte = fmt + 2; |
|---|
| 89 | | key = fmte; |
|---|
| 90 | | while(*fmte && *fmte != closer) fmte++; |
|---|
| 91 | | if(*fmte == closer) { |
|---|
| 92 | | /* We have a full key here */ |
|---|
| 93 | | const char *replacement, *oper, *nkey; |
|---|
| 94 | | intperpolate_oper_fn oper_sprint; |
|---|
| 95 | | |
|---|
| 96 | | /* keys can be of the form: :operator:key */ |
|---|
| 97 | | oper = key; |
|---|
| 98 | | if(*oper == ':' && |
|---|
| 99 | | (nkey = strnstrn(":", 1, oper + 1, fmte - key - 1)) != NULL) { |
|---|
| 100 | | void *voper; |
|---|
| 101 | | oper++; |
|---|
| 102 | | /* find oper, nkey-oper */ |
|---|
| 103 | | if(!noit_hash_retrieve(&interpolation_operators, |
|---|
| 104 | | oper, nkey - oper, |
|---|
| 105 | | &voper)) { |
|---|
| 106 | | /* else oper <- copy */ |
|---|
| 107 | | oper_sprint = interpolate_oper_copy; |
|---|
| 108 | | } |
|---|
| 109 | | else |
|---|
| 110 | | oper_sprint = (intperpolate_oper_fn)voper; |
|---|
| 111 | | nkey++; |
|---|
| 112 | | } |
|---|
| 113 | | else { |
|---|
| 114 | | oper_sprint = interpolate_oper_copy; |
|---|
| 115 | | nkey = key; |
|---|
| 116 | | } |
|---|
| 117 | | if(!noit_hash_retr_str((closer == '}') ? config : attrs, |
|---|
| 118 | | nkey, fmte - nkey, &replacement)) |
|---|
| 119 | | replacement = ""; |
|---|
| 120 | | fmt = fmte + 1; /* Format points just after the end of the key */ |
|---|
| 121 | | cp += oper_sprint(cp, end-cp, replacement); |
|---|
| 122 | | *(end-1) = '\0'; /* In case the oper_sprint didn't teminate */ |
|---|
| 123 | | replaced_something = 1; |
|---|
| 124 | | break; |
|---|
| 125 | | } |
|---|
| 126 | | } |
|---|
| 127 | | default: |
|---|
| 128 | | *cp++ = *fmt++; |
|---|
| 129 | | } |
|---|
| 130 | | } |
|---|
| 131 | | *cp = '\0'; |
|---|
| 132 | | if(copy) free(copy); |
|---|
| 133 | | if(replaced_something) |
|---|
| 134 | | copy = strdup(buff); |
|---|
| 135 | | fmt = copy; |
|---|
| 136 | | } |
|---|
| 137 | | return strlen(buff); |
|---|
| 138 | | } |
|---|
| 210 | | noit_check_make_attrs(noit_check_t *check, noit_hash_table *attrs) { |
|---|
| 211 | | #define CA_STORE(a,b) noit_hash_store(attrs, a, strlen(a), b) |
|---|
| 212 | | CA_STORE("target", check->target); |
|---|
| 213 | | CA_STORE("name", check->name); |
|---|
| 214 | | CA_STORE("module", check->module); |
|---|
| 215 | | } |
|---|
| 216 | | void |
|---|
| 217 | | noit_check_release_attrs(noit_hash_table *attrs) { |
|---|
| 218 | | noit_hash_destroy(attrs, NULL, NULL); |
|---|
| 219 | | } |
|---|
| 220 | | |
|---|
| 221 | | void |
|---|
| 222 | | noit_check_extended_id_split(const char *in, int len, |
|---|
| 223 | | char *target, int target_len, |
|---|
| 224 | | char *module, int module_len, |
|---|
| 225 | | char *name, int name_len, |
|---|
| 226 | | char *uuid, int uuid_len) { |
|---|
| 227 | | if(target) *target = '\0'; |
|---|
| 228 | | if(module) *module = '\0'; |
|---|
| 229 | | if(name) *name = '\0'; |
|---|
| 230 | | if(uuid) *uuid = '\0'; |
|---|
| 231 | | if(len >= UUID_STR_LEN) { |
|---|
| 232 | | memcpy(uuid, in + len - UUID_STR_LEN, UUID_STR_LEN); |
|---|
| 233 | | uuid[UUID_STR_LEN] = '\0'; |
|---|
| 234 | | } |
|---|
| 235 | | if(len > UUID_STR_LEN) { |
|---|
| 236 | | const char *tcp = in; |
|---|
| 237 | | const char *mcp, *ncp, *ucp; |
|---|
| 238 | | /* find the end of the target */ |
|---|
| 239 | | mcp = strchr(tcp,'`'); |
|---|
| 240 | | if(!mcp) return; |
|---|
| 241 | | /* copy in the target */ |
|---|
| 242 | | if(target_len > mcp-tcp) { |
|---|
| 243 | | memcpy(target,tcp,mcp-tcp); |
|---|
| 244 | | target[mcp-tcp] = '\0'; |
|---|
| 245 | | } |
|---|
| 246 | | mcp++; |
|---|
| 247 | | ncp = strchr(mcp,'`'); |
|---|
| 248 | | if(!ncp) return; |
|---|
| 249 | | /* copy in the module */ |
|---|
| 250 | | if(module_len > ncp-mcp) { |
|---|
| 251 | | memcpy(module,mcp,ncp-mcp); |
|---|
| 252 | | module[ncp-mcp] = '\0'; |
|---|
| 253 | | } |
|---|
| 254 | | ncp++; |
|---|
| 255 | | /* copy in the name */ |
|---|
| 256 | | ucp = in + len - UUID_STR_LEN - 1; |
|---|
| 257 | | if(ncp < ucp) { |
|---|
| 258 | | if(name_len > ucp-ncp) { |
|---|
| 259 | | memcpy(name, ncp, ucp-ncp); |
|---|
| 260 | | name[ucp-ncp] = '\0'; |
|---|
| 261 | | } |
|---|
| 262 | | } |
|---|
| 263 | | } |
|---|
| 264 | | } |
|---|
| 265 | | |
|---|
| 266 | | void |
|---|