| 1374 | } |
| 1375 | |
| 1376 | AP_DECLARE(const char *) ap_resolve_env(apr_pool_t *p, const char * word) |
| 1377 | { |
| 1378 | # define SMALL_EXPANSION 5 |
| 1379 | struct sll { |
| 1380 | struct sll *next; |
| 1381 | const char *string; |
| 1382 | apr_size_t len; |
| 1383 | } *result, *current, sresult[SMALL_EXPANSION]; |
| 1384 | char *res_buf, *cp; |
| 1385 | const char *s, *e, *ep; |
| 1386 | unsigned spc; |
| 1387 | apr_size_t outlen; |
| 1388 | |
| 1389 | s = ap_strchr_c(word, '$'); |
| 1390 | if (!s) { |
| 1391 | return word; |
| 1392 | } |
| 1393 | |
| 1394 | /* well, actually something to do */ |
| 1395 | ep = word + strlen(word); |
| 1396 | spc = 0; |
| 1397 | result = current = &(sresult[spc++]); |
| 1398 | current->next = NULL; |
| 1399 | current->string = word; |
| 1400 | current->len = s - word; |
| 1401 | outlen = current->len; |
| 1402 | |
| 1403 | do { |
| 1404 | /* prepare next entry */ |
| 1405 | if (current->len) { |
| 1406 | current->next = (spc < SMALL_EXPANSION) |
| 1407 | ? &(sresult[spc++]) |
| 1408 | : (struct sll *)apr_palloc(p, |
| 1409 | sizeof(*current->next)); |
| 1410 | current = current->next; |
| 1411 | current->next = NULL; |
| 1412 | current->len = 0; |
| 1413 | } |
| 1414 | |
| 1415 | if (*s == '$') { |
| 1416 | if (s[1] == '{' && (e = ap_strchr_c(s+2, '}'))) { |
| 1417 | char *name = apr_pstrmemdup(p, s+2, e-s-2); |
| 1418 | word = NULL; |
| 1419 | if (server_config_defined_vars) |
| 1420 | word = apr_table_get(server_config_defined_vars, name); |
| 1421 | if (!word) |
| 1422 | word = apr_pstrdup(p, getenv(name)); |
| 1423 | if (word) { |
| 1424 | current->string = word; |
| 1425 | current->len = strlen(word); |
| 1426 | outlen += current->len; |
| 1427 | } |
| 1428 | else { |
| 1429 | if (ap_strchr(name, ':') == 0) |
| 1430 | ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, APLOGNO(00111) |
| 1431 | "Config variable ${%s} is not defined", |
| 1432 | name); |
| 1433 | current->string = s; |
no test coverage detected