Files
Riccardo Magliocchetti 4f57ef33af Revert "yaml: fix memory leak"
This reverts commit ba3ac9ad09.

Since it looks like add_export_option does not copy the string we
shouldn't free it.
2013-12-27 19:16:59 +01:00

288 lines
4.9 KiB
C

#ifdef UWSGI_YAML
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifndef UWSGI_LIBYAML
/*
yaml file must be read ALL into memory.
This memory must not be freed for all the server lifecycle
*/
void yaml_rstrip(char *line) {
off_t i;
for (i = strlen(line) - 1; i >= 0; i--) {
if (line[i] == ' ' || line[i] == '\t') {
line[i] = 0;
continue;
}
break;
}
}
char *yaml_lstrip(char *line) {
off_t i;
char *ptr = line;
for (i = 0; i < (int) strlen(line); i++) {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
}
break;
}
return ptr;
}
int yaml_get_depth(char *line) {
off_t i;
int depth = 0;
for (i = 0; i < (int) strlen(line); i++) {
if (line[i] == ' ') {
depth++;
continue;
}
else if (line[i] == '\t' || line[i] == '\r') {
depth += 8;
continue;
}
break;
}
return depth;
}
char *yaml_get_line(char *yaml, size_t size) {
size_t i;
char *ptr = yaml;
int comment = 0;
for (i = 0; i < size; i++) {
ptr++;
if (yaml[i] == '#') {
yaml[i] = 0;
comment = 1;
}
else if (yaml[i] == '\n') {
yaml[i] = 0;
return ptr;
}
else if (comment) {
yaml[i] = 0;
}
}
// check if it is a stupid file without \n at the end
if (ptr > yaml) {
return ptr;
}
return NULL;
}
#else
#include <yaml.h>
#endif
void uwsgi_yaml_config(char *file, char *magic_table[]) {
size_t len = 0;
char *yaml;
int in_uwsgi_section = 0;
char *key = NULL;
char *val = NULL;
char *section_asked = "uwsgi";
char *colon;
if (uwsgi_check_scheme(file)) {
colon = uwsgi_get_last_char(file, '/');
colon = uwsgi_get_last_char(colon, ':');
}
else {
colon = uwsgi_get_last_char(file, ':');
}
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
section_asked = colon + 1;
}
}
uwsgi_log_initial("[uWSGI] getting YAML configuration from %s\n", file);
yaml = uwsgi_open_and_read(file, &len, 1, magic_table);
#ifdef UWSGI_LIBYAML
yaml_parser_t parser;
yaml_token_t token;
int status = 0;
int parsing = 1;
if (!yaml_parser_initialize(&parser)) {
uwsgi_log("unable to initialize YAML parser (libyaml)\n");
exit(1);
}
yaml_parser_set_input_string(&parser, (unsigned char *) yaml, (size_t) len - 1);
while (parsing) {
if (!yaml_parser_scan(&parser, &token)) {
uwsgi_log("error parsing YAML file: %s (%c)\n", parser.problem, yaml[parser.problem_offset]);
exit(1);
}
switch (token.type) {
case YAML_STREAM_END_TOKEN:
parsing = 0;
break;
case YAML_KEY_TOKEN:
status = 1;
break;
case YAML_VALUE_TOKEN:
status = 2;
break;
case YAML_FLOW_SEQUENCE_START_TOKEN:
case YAML_BLOCK_SEQUENCE_START_TOKEN:
status = 3;
break;
case YAML_BLOCK_MAPPING_START_TOKEN:
if (!in_uwsgi_section) {
if (key) {
if (!strcmp(section_asked, key)) {
in_uwsgi_section = 1;
}
}
}
break;
case YAML_BLOCK_END_TOKEN:
if (in_uwsgi_section) {
parsing = 0;
break;
}
break;
case YAML_SCALAR_TOKEN:
case YAML_FLOW_ENTRY_TOKEN:
case YAML_BLOCK_ENTRY_TOKEN:
if (status == 1) {
key = (char *) token.data.scalar.value;
}
else if (status == 2) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
status = 0;
}
else if (status == 3) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
}
else {
uwsgi_log("unsupported YAML token in %s block\n", section_asked);
parsing = 0;
break;
}
break;
default:
status = 0;
}
}
#else
int depth;
int current_depth = 0;
int lines = 1;
char *yaml_line;
char *section = "";
while (len) {
yaml_line = yaml_get_line(yaml, len);
if (yaml_line == NULL) {
break;
}
lines++;
// skip empty line
if (yaml[0] == 0)
goto next;
depth = yaml_get_depth(yaml);
if (depth <= current_depth) {
current_depth = depth;
// end the parsing cycle
if (in_uwsgi_section)
return;
}
else if (depth > current_depth && !in_uwsgi_section) {
goto next;
}
key = yaml_lstrip(yaml);
// skip empty line
if (key[0] == 0)
goto next;
// skip list and {} defined dict
if (key[0] == '-' || key[0] == '[' || key[0] == '{') {
if (in_uwsgi_section)
return;
goto next;
}
if (!in_uwsgi_section) {
section = strchr(key, ':');
if (!section)
goto next;
section[0] = 0;
if (!strcmp(key, section_asked)) {
in_uwsgi_section = 1;
}
}
else {
// get dict value
val = strstr(key, ": ");
if (!val) {
val = strstr(key, ":\t");
}
if (!val)
return;
// get the right key
val[0] = 0;
// yeah overengeneering....
yaml_rstrip(key);
val = yaml_lstrip(val + 2);
yaml_rstrip(val);
//uwsgi_log("YAML: %s = %s\n", key, val);
add_exported_option((char *) key, val, 0);
}
next:
len -= (yaml_line - yaml);
yaml += (yaml_line - yaml);
}
#endif
if (colon) colon[0] = ':';
}
#endif