root/trunk/freewrt/tools/config/confdata.c

Revision 3978, 9.2 kB (checked in by tg, 5 months ago)

• raise the #142 line length fixed limit (yuk) further,

to avoid segfaulting (or worse) with even longer ssh pubkeys

• MFC the colourkey patch from r2424 while here

Line 
1 /*
2  * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>
3  * Released under the terms of the GNU GPL v2.0.
4  */
5
6 #include <sys/stat.h>
7 #include <ctype.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12
13 #define LKC_DIRECT_LINK
14 #include "lkc.h"
15
16 int output_mode = 0;
17
18 const char conf_def_filename[] = ".config";
19
20 const char conf_defname[] = "Config.default";
21
22 const char *conf_confnames[] = {
23         ".config",
24         conf_defname,
25         NULL,
26 };
27
28 static char *conf_expand_value(const char *in)
29 {
30         struct symbol *sym;
31         const char *src;
32         static char res_value[SYMBOL_MAXLENGTH];
33         char *dst, name[SYMBOL_MAXLENGTH];
34
35         res_value[0] = 0;
36         dst = name;
37         while ((src = strchr(in, '$'))) {
38                 strncat(res_value, in, src - in);
39                 src++;
40                 dst = name;
41                 while (isalnum(*src) || *src == '_')
42                         *dst++ = *src++;
43                 *dst = 0;
44                 sym = sym_lookup(name, 0);
45                 sym_calc_value(sym);
46                 strcat(res_value, sym_get_string_value(sym));
47                 in = src;
48         }
49         strcat(res_value, in);
50
51         return res_value;
52 }
53
54 char *conf_get_default_confname(void)
55 {
56         struct stat buf;
57         static char fullname[PATH_MAX+1];
58         char *env, *name;
59
60         name = conf_expand_value(conf_defname);
61         env = getenv(SRCTREE);
62         if (env) {
63                 sprintf(fullname, "%s/%s", env, name);
64                 if (!stat(fullname, &buf))
65                         return fullname;
66         }
67         return name;
68 }
69
70 int conf_read(const char *name)
71 {
72         FILE *in = NULL;
73         char line[32768];
74         char *p, *p2;
75         int lineno = 0;
76         struct symbol *sym;
77         struct property *prop;
78         struct expr *e;
79         int i;
80
81         if (name) {
82                 in = zconf_fopen(name);
83         } else {
84                 const char **names = conf_confnames;
85                 while ((name = *names++)) {
86                         name = conf_expand_value(name);
87                         in = zconf_fopen(name);
88                         if (in) {
89                                 printf("#\n"
90                                        "# using defaults found in %s\n"
91                                        "#\n", name);
92                                 break;
93                         }
94                 }
95         }
96
97         if (!in)
98                 return 1;
99
100         for_all_symbols(i, sym) {
101                 sym->flags |= SYMBOL_NEW | SYMBOL_CHANGED;
102                 sym->flags &= ~SYMBOL_VALID;
103                 switch (sym->type) {
104                 case S_INT:
105                 case S_HEX:
106                 case S_STRING:
107                         if (sym->user.val)
108                                 free(sym->user.val);
109                 default:
110                         sym->user.val = NULL;
111                         sym->user.tri = no;
112                 }
113         }
114
115         while (fgets(line, sizeof(line), in)) {
116                 lineno++;
117                 sym = NULL;
118                 switch (line[0]) {
119                 case '#':
120                         if (line[1]!=' ')
121                                 continue;
122                         p = strchr(line + 2, ' ');
123                         if (!p)
124                                 continue;
125                         *p++ = 0;
126                         if (strncmp(p, "is not set", 10))
127                                 continue;
128                         sym = sym_find(line + 2);
129                         if (!sym) {
130                                 fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line + 2);
131                                 break;
132                         }
133                         switch (sym->type) {
134                         case S_BOOLEAN:
135                         case S_TRISTATE:
136                                 sym->user.tri = no;
137                                 sym->flags &= ~SYMBOL_NEW;
138                                 break;
139                         default:
140                                 ;
141                         }
142                         break;
143
144                 case 'A' ... 'Z':
145                         p = strchr(line, '=');
146                         if (!p)
147                                 continue;
148                         *p++ = 0;
149                         p2 = strchr(p, '\n');
150                         if (p2)
151                                 *p2 = 0;
152                         sym = sym_find(line);
153                         if (!sym) {
154                                 fprintf(stderr, "%s:%d: trying to assign nonexistent symbol %s\n", name, lineno, line);
155                                 break;
156                         }
157                         switch (sym->type) {
158                         case S_TRISTATE:
159                                 if (p[0] == 'm') {
160                                         sym->user.tri = mod;
161                                         sym->flags &= ~SYMBOL_NEW;
162                                         break;
163                                 }
164                         case S_BOOLEAN:
165                                 if (p[0] == 'y') {
166                                         sym->user.tri = yes;
167                                         sym->flags &= ~SYMBOL_NEW;
168                                         break;
169                                 }
170                                 if (p[0] == 'n') {
171                                         sym->user.tri = no;
172                                         sym->flags &= ~SYMBOL_NEW;
173                                         break;
174                                 }
175                                 break;
176                         case S_STRING:
177                                 if (*p++ != '"')
178                                         break;
179                                 for (p2 = p; (p2 = strpbrk(p2, "\"\\")); p2++) {
180                                         if (*p2 == '"') {
181                                                 *p2 = 0;
182                                                 break;
183                                         }
184                                         memmove(p2, p2 + 1, strlen(p2));
185                                 }
186                                 if (!p2) {
187                                         fprintf(stderr, "%s:%d: invalid string found\n", name, lineno);
188                                         exit(1);
189                                 }
190                         case S_INT:
191                         case S_HEX:
192                                 if (sym_string_valid(sym, p)) {
193                                         sym->user.val = strdup(p);
194                                         sym->flags &= ~SYMBOL_NEW;
195                                 } else {
196                                         fprintf(stderr, "%s:%d: symbol value '%s' invalid for %s\n", name, lineno, p, sym->name);
197                                         exit(1);
198                                 }
199                                 break;
200                         default:
201                                 ;
202                         }
203                         break;
204                 case '\n':
205                         break;
206                 default:
207                         continue;
208                 }
209                 if (sym && sym_is_choice_value(sym)) {
210                         struct symbol *cs = prop_get_symbol(sym_get_choice_prop(sym));
211                         switch (sym->user.tri) {
212                         case no:
213                                 break;
214                         case mod:
215                                 if (cs->user.tri == yes)
216                                         /* warn? */;
217                                 break;
218                         case yes:
219                                 if (cs->user.tri != no)
220                                         /* warn? */;
221                                 cs->user.val = sym;
222                                 break;
223                         }
224                         cs->user.tri = E_OR(cs->user.tri, sym->user.tri);
225                         cs->flags &= ~SYMBOL_NEW;
226                 }
227         }
228         fclose(in);
229
230         if (modules_sym)
231                 sym_calc_value(modules_sym);
232         for_all_symbols(i, sym) {
233                 sym_calc_value(sym);
234                 if (sym_has_value(sym) && !sym_is_choice_value(sym)) {
235                         if (sym->visible == no)
236                                 sym->flags |= SYMBOL_NEW;
237                         switch (sym->type) {
238                         case S_STRING:
239                         case S_INT:
240                         case S_HEX:
241                                 if (!sym_string_within_range(sym, sym->user.val))
242                                         sym->flags |= SYMBOL_NEW;
243                         default:
244                                 break;
245                         }
246                 }
247                 if (!sym_is_choice(sym))
248                         continue;
249                 prop = sym_get_choice_prop(sym);
250                 for (e = prop->expr; e; e = e->left.expr)
251                         if (e->right.sym->visible != no)
252                                 sym->flags |= e->right.sym->flags & SYMBOL_NEW;
253         }
254
255         sym_change_count = 1;
256
257         return 0;
258 }
259
260 int conf_write(const char *name)
261 {
262         FILE *out, *out_h;
263         struct symbol *sym;
264         struct menu *menu;
265         const char *basename;
266         char dirname[128], tmpname[128], newname[128];
267         int type, l;
268         const char *str;
269
270         dirname[0] = 0;
271         if (name && name[0]) {
272                 struct stat st;
273                 char *slash;
274
275                 if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
276                         strcpy(dirname, name);
277                         strcat(dirname, "/");
278                         basename = conf_def_filename;
279                 } else if ((slash = strrchr(name, '/'))) {
280                         int size = slash - name + 1;
281                         memcpy(dirname, name, size);
282                         dirname[size] = 0;
283                         if (slash[1])
284                                 basename = slash + 1;
285                         else
286                                 basename = conf_def_filename;
287                 } else
288                         basename = name;
289         } else
290                 basename = conf_def_filename;
291
292         sprintf(newname, "%s.tmpconfig.%d", dirname, getpid());
293         out = fopen(newname, "w");
294         if (!out)
295                 return 1;
296         out_h = NULL;
297         if (!name) {
298                 out_h = fopen(".tmpconfig.h", "w");
299                 if (!out_h)
300                         return 1;
301         }
302         fprintf(out, "#\n"
303                      "# Automatically generated make config: don't edit\n"
304                      "#\n");
305         if (out_h) {
306                 fprintf(out_h, "/*\n"
307                              " * Automatically generated header file: don't edit\n"
308                              " */\n\n"
309                              "#define AUTOCONF_INCLUDED\n\n"
310                              "/* Version Number */\n"
311                              "#define BB_VER \"%s\"\n"
312                              "#define BB_BT \"%s\"\n",
313                              getenv("VERSION"),
314                              getenv("BUILDTIME"));
315                 if (getenv("EXTRA_VERSION"))
316                         fprintf(out_h, "#define BB_EXTRA_VERSION \"%s\"\n",
317                                      getenv("EXTRA_VERSION"));
318                 fprintf(out_h, "\n");
319         }
320
321         if (!sym_change_count)
322                 sym_clear_all_valid();
323
324         menu = rootmenu.list;
325         while (menu) {
326                 sym = menu->sym;
327                 if (!sym) {
328                         if (!menu_is_visible(menu))
329                                 goto next;
330                         str = menu_get_prompt(menu);
331                         fprintf(out, "\n"
332                                      "#\n"
333                                      "# %s\n"
334                                      "#\n", str);
335                         if (out_h)
336                                 fprintf(out_h, "\n"
337                                                "/*\n"
338                                                " * %s\n"
339                                                " */\n", str);
340                 } else if (!(sym->flags & SYMBOL_CHOICE)) {
341                         sym_calc_value(sym);
342                         if (!(sym->flags & SYMBOL_WRITE) && !output_mode)
343                                 goto next;
344                         sym->flags &= ~SYMBOL_WRITE;
345                         type = sym->type;
346                         if (type == S_TRISTATE) {
347                                 sym_calc_value(modules_sym);
348                                 if (modules_sym->curr.tri == no)
349                                         type = S_BOOLEAN;
350                         }
351                         switch (type) {
352                         case S_BOOLEAN:
353                         case S_TRISTATE:
354                                 switch (sym_get_tristate_value(sym)) {
355                                 case no:
356                                         fprintf(out, "# %s is not set\n", sym->name);
357                                         if (out_h)
358                                                 fprintf(out_h, "#undef %s\n", sym->name);
359                                         break;
360                                 case mod:
361                                         fprintf(out, "%s=m\n", sym->name);
362 #if 0
363                                         if (out_h)
364                                                 fprintf(out_h, "#define %s_MODULE 1\n", sym->name);
365 #endif
366                                         break;
367                                 case yes:
368                                         fprintf(out, "%s=y\n", sym->name);
369                                         if (out_h)
370                                                 fprintf(out_h, "#define %s 1\n", sym->name);
371                                         break;
372                                 }
373                                 break;
374                         case S_STRING:
375                                 // fix me
376                                 str = sym_get_string_value(sym);
377                                 fprintf(out, "%s=\"", sym->name);
378                                 if (out_h)
379                                         fprintf(out_h, "#define %s \"", sym->name);
380                                 do {
381                                         l = strcspn(str, "\"\\");
382                                         if (l) {
383                                                 fwrite(str, l, 1, out);
384                                                 if (out_h)
385                                                         fwrite(str, l, 1, out_h);
386                                         }
387                                         str += l;
388                                         while (*str == '\\' || *str == '"') {
389                                                 fprintf(out, "\\%c", *str);
390                                                 if (out_h)
391                                                         fprintf(out_h, "\\%c", *str);
392                                                 str++;
393                                         }
394                                 } while (*str);
395                                 fputs("\"\n", out);
396                                 if (out_h)
397                                         fputs("\"\n", out_h);
398                                 break;
399                         case S_HEX:
400                                 str = sym_get_string_value(sym);
401                                 if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
402                                         fprintf(out, "%s=%s\n", sym->name, str);
403                                         if (out_h)
404                                                 fprintf(out_h, "#define %s 0x%s\n", sym->name, str);
405                                         break;
406                                 }
407                         case S_INT:
408                                 str = sym_get_string_value(sym);
409                                 fprintf(out, "%s=%s\n", sym->name, str);
410                                 if (out_h)
411                                         fprintf(out_h, "#define %s %s\n", sym->name, str);
412                                 break;
413                         }
414                 }
415
416         next:
417                 if (menu->list) {
418                         menu = menu->list;
419                         continue;
420                 }
421                 if (menu->next)
422                         menu = menu->next;
423                 else while ((menu = menu->parent)) {
424                         if (menu->next) {
425                                 menu = menu->next;
426                                 break;
427                         }
428                 }
429         }
430         fclose(out);
431         if (out_h) {
432                 fclose(out_h);
433                 rename(".tmpconfig.h", "include/config.h");
434                 file_write_dep(NULL);
435         }
436         if (!name || basename != conf_def_filename) {
437                 if (!name)
438                         name = conf_def_filename;
439                 sprintf(tmpname, "%s.old", name);
440                 rename(name, tmpname);
441         }
442         sprintf(tmpname, "%s%s", dirname, basename);
443         if (rename(newname, tmpname))
444                 return 1;
445
446         sym_change_count = 0;
447
448         return 0;
449 }
Note: See TracBrowser for help on using the browser.