]> gitweb.ps.run Git - ps-cgit/blob - configfile.c
clone: use cgit_print_error_page() instead of html_status()
[ps-cgit] / configfile.c
1 /* configfile.c: parsing of config files
2  *
3  * Copyright (C) 2006-2014 cgit Development Team <cgit@lists.zx2c4.com>
4  *
5  * Licensed under GNU General Public License v2
6  *   (see COPYING for full license text)
7  */
8
9 #include <git-compat-util.h>
10 #include "configfile.h"
11
12 static int next_char(FILE *f)
13 {
14         int c = fgetc(f);
15         if (c == '\r') {
16                 c = fgetc(f);
17                 if (c != '\n') {
18                         ungetc(c, f);
19                         c = '\r';
20                 }
21         }
22         return c;
23 }
24
25 static void skip_line(FILE *f)
26 {
27         int c;
28
29         while ((c = next_char(f)) && c != '\n' && c != EOF)
30                 ;
31 }
32
33 static int read_config_line(FILE *f, struct strbuf *name, struct strbuf *value)
34 {
35         int c = next_char(f);
36
37         strbuf_reset(name);
38         strbuf_reset(value);
39
40         /* Skip comments and preceding spaces. */
41         for(;;) {
42                 if (c == '#' || c == ';')
43                         skip_line(f);
44                 else if (!isspace(c))
45                         break;
46                 c = next_char(f);
47         }
48
49         /* Read variable name. */
50         while (c != '=') {
51                 if (c == '\n' || c == EOF)
52                         return 0;
53                 strbuf_addch(name, c);
54                 c = next_char(f);
55         }
56
57         /* Read variable value. */
58         c = next_char(f);
59         while (c != '\n' && c != EOF) {
60                 strbuf_addch(value, c);
61                 c = next_char(f);
62         }
63
64         return 1;
65 }
66
67 int parse_configfile(const char *filename, configfile_value_fn fn)
68 {
69         static int nesting;
70         struct strbuf name = STRBUF_INIT;
71         struct strbuf value = STRBUF_INIT;
72         FILE *f;
73
74         /* cancel deeply nested include-commands */
75         if (nesting > 8)
76                 return -1;
77         if (!(f = fopen(filename, "r")))
78                 return -1;
79         nesting++;
80         while (read_config_line(f, &name, &value))
81                 fn(name.buf, value.buf);
82         nesting--;
83         fclose(f);
84         strbuf_release(&name);
85         strbuf_release(&value);
86         return 0;
87 }
88