519fecfee4cd7344b538528f7fa923b7fda280d2
1
2#include "cache.h"
3
4#define MAXNAME (256)
5
6static FILE *config_file;
7static int config_linenr;
8static int get_next_char(void)
9{
10 int c;
11 FILE *f;
12
13 c = '\n';
14 if ((f = config_file) != NULL) {
15 c = fgetc(f);
16 if (c == '\n')
17 config_linenr++;
18 if (c == EOF) {
19 config_file = NULL;
20 c = '\n';
21 }
22 }
23 return c;
24}
25
26static char *parse_value(void)
27{
28 static char value[1024];
29 int quote = 0, comment = 0, len = 0, space = 0;
30
31 for (;;) {
32 int c = get_next_char();
33 if (len >= sizeof(value))
34 return NULL;
35 if (c == '\n') {
36 if (quote)
37 return NULL;
38 value[len] = 0;
39 return value;
40 }
41 if (comment)
42 continue;
43 if (isspace(c) && !quote) {
44 space = 1;
45 continue;
46 }
47 if (space) {
48 if (len)
49 value[len++] = ' ';
50 space = 0;
51 }
52 if (c == '\\') {
53 c = get_next_char();
54 switch (c) {
55 case '\n':
56 continue;
57 case 't':
58 c = '\t';
59 break;
60 case 'b':
61 c = '\b';
62 break;
63 case 'n':
64 c = '\n';
65 break;
66 /* Some characters escape as themselves */
67 case '\\': case '"':
68 break;
69 /* Reject unknown escape sequences */
70 default:
71 return NULL;
72 }
73 value[len++] = c;
74 continue;
75 }
76 if (c == '"') {
77 quote = 1-quote;
78 continue;
79 }
80 if (!quote) {
81 if (c == ';' || c == '#') {
82 comment = 1;
83 continue;
84 }
85 }
86 value[len++] = c;
87 }
88}
89
90static int get_value(config_fn_t fn, char *name, unsigned int len)
91{
92 int c;
93 char *value;
94
95 /* Get the full name */
96 for (;;) {
97 c = get_next_char();
98 if (c == EOF)
99 break;
100 if (!isalnum(c))
101 break;
102 name[len++] = tolower(c);
103 if (len >= MAXNAME)
104 return -1;
105 }
106 name[len] = 0;
107 while (c == ' ' || c == '\t')
108 c = get_next_char();
109
110 value = NULL;
111 if (c != '\n') {
112 if (c != '=')
113 return -1;
114 value = parse_value();
115 if (!value)
116 return -1;
117 }
118 return fn(name, value);
119}
120
121static int get_base_var(char *name)
122{
123 int baselen = 0;
124
125 for (;;) {
126 int c = get_next_char();
127 if (c == EOF)
128 return -1;
129 if (c == ']')
130 return baselen;
131 if (!isalnum(c))
132 return -1;
133 if (baselen > MAXNAME / 2)
134 return -1;
135 name[baselen++] = tolower(c);
136 }
137}
138
139static int git_parse_file(config_fn_t fn)
140{
141 int comment = 0;
142 int baselen = 0;
143 static char var[MAXNAME];
144
145 for (;;) {
146 int c = get_next_char();
147 if (c == '\n') {
148 /* EOF? */
149 if (!config_file)
150 return 0;
151 comment = 0;
152 continue;
153 }
154 if (comment || isspace(c))
155 continue;
156 if (c == '#' || c == ';') {
157 comment = 1;
158 continue;
159 }
160 if (c == '[') {
161 baselen = get_base_var(var);
162 if (baselen <= 0)
163 break;
164 var[baselen++] = '.';
165 var[baselen] = 0;
166 continue;
167 }
168 if (!isalpha(c))
169 break;
170 var[baselen] = tolower(c);
171 if (get_value(fn, var, baselen+1) < 0)
172 break;
173 }
174 die("bad config file line %d", config_linenr);
175}
176
177int git_config_int(const char *name, const char *value)
178{
179 if (value && *value) {
180 char *end;
181 int val = strtol(value, &end, 0);
182 if (!*end)
183 return val;
184 }
185 die("bad config value for '%s'", name);
186}
187
188int git_config_bool(const char *name, const char *value)
189{
190 if (!value)
191 return 1;
192 if (!*value)
193 return 0;
194 if (!strcasecmp(value, "true"))
195 return 1;
196 if (!strcasecmp(value, "false"))
197 return 0;
198 return git_config_int(name, value) != 0;
199}
200
201int git_default_config(const char *var, const char *value)
202{
203 /* This needs a better name */
204 if (!strcmp(var, "core.filemode")) {
205 trust_executable_bit = git_config_bool(var, value);
206 return 0;
207 }
208
209 if (!strcmp(var, "user.name")) {
210 strncpy(git_default_name, value, sizeof(git_default_name));
211 return 0;
212 }
213
214 if (!strcmp(var, "user.email")) {
215 strncpy(git_default_email, value, sizeof(git_default_email));
216 return 0;
217 }
218
219 /* Add other config variables here.. */
220 return 0;
221}
222
223int git_config(config_fn_t fn)
224{
225 int ret;
226 FILE *f = fopen(git_path("config"), "r");
227
228 ret = -1;
229 if (f) {
230 config_file = f;
231 config_linenr = 1;
232 ret = git_parse_file(fn);
233 fclose(f);
234 }
235 return ret;
236}