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