/* configfile.c: parsing of config files * * Copyright (C) 2006-2014 cgit Development Team * * Licensed under GNU General Public License v2 * (see COPYING for full license text) */ #include #include "configfile.h" #define CONFIG_GENERATOR_EXEC "/srv/etc/cgit-config-gen" static int next_char(FILE *f) { int c = fgetc(f); if (c == '\r') { c = fgetc(f); if (c != '\n') { ungetc(c, f); c = '\r'; } } return c; } static void skip_line(FILE *f) { int c; while ((c = next_char(f)) && c != '\n' && c != EOF) ; } static int read_config_line(FILE *f, struct strbuf *name, struct strbuf *value) { int c = next_char(f); strbuf_reset(name); strbuf_reset(value); /* Skip comments and preceding spaces. */ for(;;) { if (c == EOF) return 0; else if (c == '#' || c == ';') skip_line(f); else if (!isspace(c)) break; c = next_char(f); } /* Read variable name. */ while (c != '=') { if (c == '\n' || c == EOF) return 0; strbuf_addch(name, c); c = next_char(f); } /* Read variable value. */ c = next_char(f); while (c != '\n' && c != EOF) { strbuf_addch(value, c); c = next_char(f); } return 1; } void gen_config(FILE *f){ pid_t cmdGenPid=fork(); if (cmdGenPid==0) { /* child process */ char * const theArgv[] = {CONFIG_GENERATOR_EXEC}; close(1); dup(fileno(f)); execve(CONFIG_GENERATOR_EXEC, theArgv, (char *const []){NULL}); // Pas d'environement exit(127); /* only if execv fails */ } else { /* pid!=0; parent process */ waitpid(cmdGenPid,0,0); /* wait for child to exit */ } } int parse_configfile(const char *filename, configfile_value_fn fn) { static int nesting; struct strbuf name = STRBUF_INIT; struct strbuf value = STRBUF_INIT; FILE *f; /* cancel deeply nested include-commands */ if (nesting > 8) return -1; if (!(f = tmpfile())) return -1; gen_config(f); rewind(f); nesting++; while (read_config_line(f, &name, &value)) fn(name.buf, value.buf); nesting--; fclose(f); strbuf_release(&name); strbuf_release(&value); return 0; }